Question

I have implemented below program for my own understanding. But I see the class name returned by typeid is slightly modified. I knew it could be because of name mangling but including extern C doesn’t help either.

Can someone please help me understand why such behavior and also how to fix it?

g++ version - 4.7.0

#include <iostream>
#include <typeinfo>

using namespace std;

class Base
{
    public:
        virtual ~Base(){}
};

class Derive : public Base
{
    public:
        ~Derive(){}
};

class newBase
{
    public:
        ~newBase(){}
};

class newDerive : public newBase
{
    public:
        ~newDerive(){}
};

int main()
{
    Base base;
    Derive derive;
    Base *pBase;
    Base & rBase1 = base;
    Base & rBase2 = derive;

    newBase newbase;
    newDerive newderive;
    newBase *pNewBase;

    //Results with polymorphic class.
    pBase = &base;
    cout<<"Base class pointer pBase contains object of type "<<typeid(*pBase).name()            <<".\n";

    pBase = &derive;
    cout<<"Base class pointer pBase contains object of type "<<typeid(*pBase).name()<<".\n";

    cout<<"\nReference variable rBase1 referring to "<<typeid(rBase1).name()<<".\n";
    cout<<"Reference variable rBase2 referring to "<<typeid(rBase2).name()<<".\n";

    //Results with non-polymorphic class.
    pNewBase = &newbase;
    cout<<"\nBase class pointer pNewBase contains object of type "<<typeid(*pNewBase).name()<<".\n";

    pNewBase = &newderive;
    cout<<"Base class pointer pNewBase contains object of type "<<typeid(*pNewBase).name()<<".\n";

    return 0;
}

Output -
Base class pointer pBase contains object of type 4Base.
Base class pointer pBase contains object of type 6Derive.

Reference variable rBase1 referring to 4Base.
Reference variable rBase2 referring to 6Derive.

Base class pointer pNewBase contains object of type 7newBase.
Base class pointer pNewBase contains object of type 7newBase.

I was expecting the class name as specified in the program.

Many thanks.

Was it helpful?

Solution

There is no requirement on what type_info::name() looks like.

The result of a typeid expression is an lvalue of static type const std::type_info (18.7.1) and dynamic type const std::type_info or const name where name is an implementation-defined class publicly derived from std::type_info

Then, about std::type_info::name():

const char* name() const;

Returns: an implementation-defined NTBS.

[...]

NTBS is simply a shorthand for null-terminated byte string.

In other words: You should not rely on any value of type_info::name().

What you actually see with g++:

Those names are mangled names, and g++'s implementation of such mangled names is based on length-prefixed strings, where each substring is the namespace name, plus some other info; but that's basically it.

For example:

unmangled: foo::bar::Frob
mangled:   3foo3bar4Frob

Example to put into your compiler:

#include <iostream>
#include <typeinfo>

namespace foo { namespace bar { 
    enum Frob {};
    class Frobnicate {};
    Frob frob;

    template <typename T> void Meh() { throw T(); }
} }

int main () {
    std::cout << typeid(foo::bar::Frob).name() << '\n'
              << typeid(foo::bar::Frobnicate).name()  << '\n'  
              << typeid(foo::bar::frob).name() << '\n'
              << typeid(foo::bar::Meh<int>).name() << '\n'
              << typeid(foo::bar::Meh<float>).name() << '\n'
    ;
}

Output for me:

N3foo3bar4FrobE
N3foo3bar10FrobnicateE
N3foo3bar4FrobE
FvvE
FvvE

The latter two show you that one even cannot rely on names being different.

OTHER TIPS

In case you are interested in "demangling" the name, g++ has a compiler-specific function to do this.

You can find an example in http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top