Skip to main content
GameDev.net gamedev.net
🔒 Locked

one variable to hold different types?

Started by silothesuper Apr 17, 2006 at 3:50 AM 10 replies 1.5k views
Original Post
silothesuper
silothesuper
I have a struct with a bunch of variables in it. I want to be able to assign either a float, int, bool or a char array to a variable in my struct. Is there a way I can have it so that I only have to have one variable to hold either the float, int, bool or char array instead of having one of each type and only using one of them? I read something about void pointers somewhere from google, I tried to use void pointers but I couldn't get it to work.
Evil Steve
Evil Steve
You want to look at unions:
struct MyStruct{   union   {      int n;      float f;      bool b;   } u;};MyStruct s;s.u.f = 0.0f;s.u.n = 42;cout << s.u.f << endl;  // Will output semi-gibberish

sizeof(MyStruct) should be 4 now (assuming 32-bit ints and floats). All 3 variables occupy the same memory space, so you can't write to both the int and the float without overwriting data.

EDIT: Fixed a typo

[Edited by - Evil Steve on April 17, 2006 4:58:23 AM]
blaze02
blaze02
There isn't really a reason to wrap the union in a struct, but unions are definitely what you want to use. Its just a struct where all members start at the same memory address. The size of your union will be the size of its largest member (+ padding).
Nuno1
Nuno1
look at the syntax of "union" in C. I think this is what you are after.

you can also do this with type casting but very unrecommended because you really do not know the variable type.

the third way is to make a C++ class and use diffrent parameters with the same function name for example :

void foo(int a);
void foo(float a);
void foo(char a);

so basicly when you pass an int to the function the foo(int a) function will be called. if float the foo(float a) will be called etc.


Cheers,
Nuno1
silothesuper
silothesuper
Thanks for your replies. Im gunna try using a union in the morning
Programmer16
Programmer16
@EvilSteve - Your code won't compile for me (says something about '.' after UDP I think.)

This is a class that I used to use a lot, and I plan to use in my scripting system:
#include <string>#include <iostream>enum VALUETYPE{    VALUE_NONE = -1,    VALUE_STRING = 0,    VALUE_INT,    VALUE_FLOAT,    VALUE_BOOL,};class Value{    //std::string m_String;    int            m_nInteger;    float          m_fFloat;    bool           m_bBoolean;    int            m_nType;public:    Value(){ m_nType = VALUE_NONE;    }    //Value(const std::string& String)     : m_String(String)     { m_nType = VALUE_STRING;  }    Value(int nInteger)                    : m_nInteger(nInteger) { m_nType = VALUE_INT;     }    Value(float fFloat)                    : m_fFloat(fFloat)     { m_nType = VALUE_FLOAT;   }    Value(bool bBoolean)                 : m_bBoolean(bBoolean)   { m_nType = VALUE_BOOL;    }    //const std::string&    GetString() const      { return m_String;      }    int                     GetInteger() const     { return m_nInteger;    }    float                   GetFloat() const       { return m_fFloat;      }    bool                    GetBoolean() const     { return m_bBoolean;    }    int                     GetType() const        { return m_nType;       }};int main(){    Value MyValue;    std::cout<<sizeof(MyValue)<<std::endl;    return 0;}


My class is a lot bigger (sizeof(Value) == 16, sizeof(Value) == 44 if you uncomment the std::string parts), but it comes in pretty handy.

Edit: You could also add some conversion operators to this class (I have in my current version of it and it works pretty good.)

[Edited by - Programmer16 on April 17, 2006 11:24:32 AM]
Nitage
Nitage
Quote:
Original post by Programmer16
@EvilSteve - Your code won't compile for me (says something about '.' after UDP I think.

This is a class that I used to use a lot, and I plan to use in my scripting system:
*** Source Snippet Removed ***

My class is a lot bigger (sizeof(Value) == 16, sizeof(Value) == 44 if you uncomment the std::string parts), but it comes in pretty handy.

Edit: You could also add some conversion operators to this class (I have in my current version of it and it works pretty good.)


What's the point of that class? It provides no checking that you're accessing the correct type, and no way to query what type is being held.
blaze02
blaze02
Quote:
Original post by Programmer16
@EvilSteve - Your code won't compile for me


His struct is empty. All it has in it is the declaration of the union type. Put
union u union_variable; //C
or just
u union_variable; //C++
in the struct.
Evil Steve
Evil Steve
Whoops, force of habbit [smile] I just automatically put a union in a struct, since you'll almost always want to provide extra information along with the union, like what type of data it contains.

@Programmer16: I use something similar in my scripting system. I'd recommend using a union to pack together all your POD types though, since a value will never be e.g. a float and and int.

I've edited my above post now. I'm particularly bad at doing that with unions...
Programmer16
Programmer16
Quote:
Original post by Nitage
Quote:
Original post by Programmer16
@EvilSteve - Your code won't compile for me (says something about '.' after UDP I think.

This is a class that I used to use a lot, and I plan to use in my scripting system:
*** Source Snippet Removed ***

My class is a lot bigger (sizeof(Value) == 16, sizeof(Value) == 44 if you uncomment the std::string parts), but it comes in pretty handy.

Edit: You could also add some conversion operators to this class (I have in my current version of it and it works pretty good.)


What's the point of that class? It provides no checking that you're accessing the correct type, and no way to query what type is being held.


The point of the class is that it holds any of the above types, and can be assigned any of those values without calling SetX(). This is the old version of my class, so it doesn't have the assignment operators, so that isn't quite as obvious.

Evidentally you missed the GetType() function? The values are private, so the user can't operate them without the methods, which I use to set m_nType.

Edit: Also, as EvilSteve said, it would be a good idea to use an union for the int, float, and bool.

[Edited by - Programmer16 on April 20, 2006 2:50:03 AM]
izhbq412
izhbq412
A more general solution to your problem is to use a type that can hold different types at run-time, like VCL's Variant type (inherited from Object Pascal).

A quick search revealed boost::any - it might be just what you're looking for ;)
___The essence of balance is detachment. To embrace a cause, to grow fond or spiteful, is to lose one''s balance after which, no action can be trusted. Our burden is not for the dependent of spirit. - Mayar, Third Keeper
Rebooted
Rebooted
A discriminated union class is usually a better solution than a raw C union, assuming you are using C++ and not C.

I'd suggest using boost::variant.

There is also boost::any, but you can't restrict the types it takes - it can hold anything.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.