22

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>
#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++)

masoud
  • 55,379
  • 16
  • 141
  • 208
  • IIRC it would be legal for a compliant implementation to just return the same string (e.g. "godzilla") for any class. – 6502 Oct 16 '11 at 20:43
  • You may like to use different naming conventions for classes and namespaces, so that you can immediately see which one is which in `X::Y::Z::MyType`. – Maxim Egorushkin Oct 17 '11 at 08:18
  • Expanding on Maxim Yegorushkin's comment, you could for example make namespace names lowercase, class names InitialCaps. Then you could tell that `foo::bar::Baz::Qux` is `namespace foo {namespace bar {struct Baz {struct Qux {};};}}`. – David Hammen Oct 17 '11 at 09:44

5 Answers5

10

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.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
3

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.

etipici
  • 415
  • 3
  • 6
  • but, this approach has an issue, it can not use in derived classes which `name()` returns derived class name! (and each derived class must override its constructor again) – masoud Oct 17 '11 at 14:24
  • @MasoudM. It is not a standad c++ feature, rather than specific to gcc and VS. But even in old versions it is provided. You can check the links about that. And yes, you're right about derived class issue. I can't figure out rigth now how to overcome that. But there should be a way:) – etipici Oct 17 '11 at 20:14
  • `__func__` was added to C++11 to officially provide this functionality, although in the form of a hidden variable rather than a macro. MSVC does not support it yet, although faking it is easy enough. – Dennis Zickefoose Oct 18 '11 at 07:36
3

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.

1

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:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Thnx for answer, but it were discussed before and i found a good practice for my project which needs a strange pattern: [http://stackoverflow.com/questions/7691697/](http://stackoverflow.com/questions/7691697/) – masoud Oct 17 '11 at 16:00
  • @MasoudM.: I just added a link. Have a look at that as well. – Nawaz Oct 17 '11 at 16:02
0
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;
}