Storing a type of a variable?

Started by
12 comments, last by Koobazaur 16 years, 3 months ago
I am creating a template class that stores a variable of the template, and I would like for the class to know what type is. Is ther any way I can store the type of the variable? From what I read, typeid won't let me save its input...
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
Advertisement
The type is implicit in case of templates:

template < class T >struct Holder{  T value;};Holder<int> int_var;std::cout << typeid(int_var.value).name() << std::endl;


This should give you the int type, since compiler creates one class for each unique Holder instance, and that one is strongly typed.
What are you actually using this for? You should rarely need to use RTTI. Polymorphism is preferable if possible.
-----------------------http://poita.org - C++ and D programming articles.
Basically I am creating a class that can take an any value, int, float, string etc. I was pondering using templates, but decided on a void pointer since it's more flexible (I can change the value of my class at any point). Setting the value is easy, but retrieving must know exactly what type it is or bad things happen. Hence why I wanted the entry to know it's own type so that it can be always checked before retrieving the value.
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
I don't know if integrating boost into your project is an option, but you might want to consider boost::any.
Aye, I know about boost::any, but I wanted to create this sort of thing myself. funnyily enough, my interface looks exactly like the one from boost::any, with templates for the = operators.

basically what I do is store a void pointer and a string that defines my typeid.name(). Everything works fine, except that I am not sure how to create the copy constructor for my class. I would need to create a copy of the pVoid, but to do that I would need to call new with the type, but is there a way to do that with just the name of the type from typeid.name() ?
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
Hm.

Well for POD it's simple, just do a memcpy of the data.

For non POD types, you have to change your implementation. You'd need a template holder class that holds the actual object that inherits from a all purpose parent holder class. Your implementation then stores a parent holder pointer instead of a void pointer. This polymorphic pointer allows you to forward the copy construction to an object that knows the held type. The holder class needs to implement a method that duplicates the object contained using new.

It's not beginner stuff, but it can be done.
Quote:Original post by King Mir
Well for POD it's simple, just do a memcpy of the data.

To do a memcpy you need to somehow translate the stored type-name into a size_t...

Quote:Original post by Koobazaur
basically what I do is store a void pointer and a string that defines my typeid.name(). Everything works fine, except that I am not sure how to create the copy constructor for my class. I would need to create a copy of the pVoid, but to do that I would need to call new with the type, but is there a way to do that with just the name of the type from typeid.name() ?

Instead of using a string, I'd use an enumeration (but that's just me). Then in your copy function, you'll have to do a switch on that enum value (or a big if/else block on your string value).
enum TypeName{ Int, Float /*etc*/};class CClass{public: CClass( const CClass& o ) : m_Type(o.m_Type) {   switch( m_Type )   {    case Int:   m_Value = new int;   *((int*)  m_Value) = o.m_Value?*((int*)  o.m_Value):0; break;    case Float: m_Value = new float; *((float*)m_Value) = o.m_Value?*((float*)o.m_Value):0; break;    default: m_Value = 0;   } }private: TypeName m_Type; void* m_Value;}


[Edited by - Hodgman on January 3, 2008 12:02:49 AM]
Quote:Original post by Hodgman
Quote:Original post by Koobazaur
basically what I do is store a void pointer and a string that defines my typeid.name(). Everything works fine, except that I am not sure how to create the copy constructor for my class. I would need to create a copy of the pVoid, but to do that I would need to call new with the type, but is there a way to do that with just the name of the type from typeid.name() ?

Instead of using a string, I'd use an enumeration (but that's just me). Then in your copy function, you'll have to do a switch on that enum value (or a big if/else block on your string value).


*** Source Snippet Removed ***

That would work, except that it would require the enumeration to store every conceivable type. That's just not practical. Even limiting ourselves to non class types, you'd have to handle multiple levels of indirection, with possible variations in constness and volatile-ness(volatility?). Consider the type:

const int * volatile *const volitile *
It depends on Koobazaur's requirements.
These kinds of loosely typed variables are generally used for scripting and the like, where keywords such as const and volatile (and to a certain degree, even pointers) are probably not often required.

With the string-based approach, wouldn't you also need to write a if/elseif/else block containing every possible type?
e.g.
if( m_strType == typeid(int).name() ) m_value = new int;
else if( m_strType == typeid(float).name() ) m_value = new float;
...

This topic is closed to new replies.

Advertisement