Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I remove the number associated with typeid( ).name( ) in C++?

I have a factory method class that generates "Items" and returns a pointer to the Item that it creates.

I have derived classes of Item. For example, Item can be a "weapon" "consumable" or "armor."

I need to detect which type of Item is created so that I can properly cast the Item to that type. I did some test lines and it looks like it's doing what I want, except for adding a number associated with the type.

Example:

I had the line:

cout << "Type Created: " << typeid(pItem).name() << endl;

Which return the base class Item, but it would display: "4Item"

I then changed that to:

cout << "Type Created: " << typeid(*pItem).name() << endl;

Which would give me the correct derived type, but also throw in that number. So I get something like "5Armor"

Why did pItem return the base class? And why does it return an int with the type? How can I remove the int?

A solution that does what I want - In a "cheating" kind of way:

            string type;
            string returnedType = typeid(*pItem1).name();
            for (int i=1; i < returnedType.length(); i++){
                    type.push_back(returnedType[i]);
            }
            cout << "type: " << type << endl;

Thanks

like image 257
Habit Avatar asked May 04 '13 23:05

Habit


2 Answers

typeid returns a const std::type_info&. The std::type_info type has a function called name that returns an implementation-defined string representation of the name of the underlying type. There are absolutely no guarantees about what this function is going to return - it doesn't have to return a string that looks anything at all like the name of the type in the original program, and can decorate it however it would like to.

If you need to keep track of the name of the type that you created, I would suggest just adding in a virtual function like this one to your hierarchy:

virtual std::string getType() const = 0;

This function could return a nice, human-readable representation of the type that is guaranteed to behave in the way that you want (because you're responsible for writing it).

Hope this helps!

like image 104
templatetypedef Avatar answered Oct 01 '22 09:10

templatetypedef


I use g++ and also had this problem. Now strictly answering your question without any intention to point what's the best approach, there is another way to deal with this case.

Here is a copy/paste example for you:

Create a type of yours, like MyType.h

#ifndef __MYTYPE_H__
#define __MYTYPE_H__
class MyType {
};
#endif

and a main.cpp file, like this:

#include <cxxabi.h>
#include <iostream>
#include <typeinfo>

#include "MyType.h"

template <typename T> char* get_typename(T& object)
{
    return abi::__cxa_demangle(typeid(object).name(), 0, 0, 0);
}

int main(int argc, char ** argv)
{
    MyType my_type;

    std::cout << get_typename(my_type) << std::endl;

    return 0;
}

This would output: MyType

I came to this solution based on an answer from this post that took me to this article.

like image 41
rbento Avatar answered Oct 01 '22 08:10

rbento