How to check data type?

I'm writing a simple program which saves all its data to xml file.
I've got a few different classes to save in it, but no idea how to differ them.
I could another string but that won't do in few cases.
Help.
Might typeid(sometype variable) be the function you are looking for?

1
2
3
4
5
6
7
8
9
10
11
12
#include <typeinfo>
#include <iostream>

class someClass { };

int main(int argc, char* argv[]) {
    int a;
    someClass b;
    std::cout<<"a is of type: "<<typeid(a).name()<<std::endl; // Output 'a is of type int'
    std::cout<<"b is of type: "<<typeid(b).name()<<std::endl; // Output 'b is of type someClass'
    return 0;
}


Maybe I just don't understand your question :-/
Yeah, that's exactly what I was looking for, thanks.
Don't use typeid for that. It was reluctantly added to the language and when used, should only be used internally. There is no guarantee that the string returned will be the same across vendors or environments or accross compiler versions ...

If fact, I'd go as far to say that if you're relying on it, you're design is sub-optimal.
Last edited on
Polymorphism could be used for this. Consider a virtual method that writes the data to disk.
closed account (1yR4jE8b)
Polymorphism doesn't apply for primitive types, but you could use specialized templates although that could get cumbersome writing a template for every primitive types.

I haven't tested this but in theory, couldn't you check primitive types simply by comparing the type_info returned by the typeid operator?

if (typeid(a) == typeid(int))
//do stuff
Last edited on
There is no guarantee that the string returned will be the same across vendors or environments or accross compiler versions ...

Amen. What he said.

Oh, and it doesn't *have* to be unique either.. ;-)

I haven't tested this but in theory, couldn't you check primitive types simply by comparing the type_info returned by the typeid operator?

1
2
if (typeid(a) == typeid(int()))
//do stuff 

That would work, but get ugly quickly. I prefer this one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Foobar;

template<typename T> struct type_name
{
    static const char* name() { static_assert(false, "You are missing a DECL_TYPE_NAME"); }
};

template<> struct type_name<int> { static const char* name() {return "int";} };
template<> struct type_name<string> { static const char* name() {return "string";} };
template<> struct type_name<Foobar> { static const char* name() {return "Foobar";} };

int main()
{
        cout << type_name<int>::name();  // prints "int"
	cout << type_name<float>::name();  // compile time error. float wasn't declared.
}


Of course, Macros can help to ease the declaration a bit:
1
2
3
4
5
6
#define DECL_TYPE_NAME(x) template<> struct type_name<x> { static const char* name() {return #x;} }

DECL_TYPE_NAME(float);
DECL_TYPE_NAME(string);
DECL_TYPE_NAME(MyClass);
...



Ciao, Imi.
PS: If your compiler doen't have "static_assert" yet, just don't implement name() alltogether. Error message is not that pretty, but you still get compile errors for missing types.
Last edited on
if (typeid(a) == typeid(int()))
Really BAD advice.

You should provide a mechanism where each type streams itself into a useable format. One example is the way the iostream library can be used to stream types a textual representation. Do the same for your XML.
I fear our OP ran away with typeid().name under his arm... *sigh*. ;-)

Ciao, Imi.
That's fine.

It'll work until he has to port his code and then he'll find all his type field is wrong and will have to recode all his data or hack is program.
closed account (1yR4jE8b)
if (typeid(a) == typeid(int))
Really BAD advice.

You should provide a mechanism where each type streams itself into a useable format. One example is the way the iostream library can be used to stream types a textual representation. Do the same for your XML.


Forgive my ignorance, but why is it bad advice?
Last edited on
Forgive my ignorance, but why is it bad advice?


Using typeid() itself is safe in in comparing it to other typeid's during the same programm execution. It's the .name() where there is no guarantee about at all.

But even for typeid, you should not store it in some file. Just think of it as some type identifier that changes every time you run your code. ;-)


The most place where typeid is used is in such if-comparison to check for the dynamic type of a base class:
1
2
3
4
5
6
7
void f (myclass* p)
{
     // do we really have a myclass? Maybe I got a subclass of myclass?
     // I really want to have myclass here, so lets check:
     if (typeid(*p) == typeid(myclass))
         ...
}


However, this code has most probably serious design problems. Most of the time you just should not have to care whether you got myclass* or a subclass of it. That's what inheritance is about, isn't it?

The same goes for integral types along a similar line of reasoning. typeid(int) != typeid(long), but most code should just not care whether he got a long when he wanted an int - as all you can do with ints you can also do with longs.. roughly said..

Ciao, Imi.
Last edited on
I fear our OP ran away with typeid().name under his arm... *sigh*. ;-)

He did not, still here.
Well, after reading everything I think I'll stay with typeid(), it will be just fine.
Thanks for your effort.
The example above built on a Microsoft compiler:
a is of type: int
b is of type: class someClass

The example above built on gcc on Windows:
a is of type: i
b is of type: 9someClass
Still fine, knowing this I can make something to prevent such behaviour. Thanks again
Topic archived. No new replies allowed.