Sign in to follow this  
silothesuper

one variable to hold different types?

Recommended Posts

silothesuper    204
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.

Share this post


Link to post
Share on other sites
Evil Steve    2017
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]

Share this post


Link to post
Share on other sites
blaze02    100
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).

Share this post


Link to post
Share on other sites
Nuno1    161
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

Share this post


Link to post
Share on other sites
Programmer16    2321
@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]

Share this post


Link to post
Share on other sites
Nitage    1107
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.

Share this post


Link to post
Share on other sites
blaze02    100
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.

Share this post


Link to post
Share on other sites
Evil Steve    2017
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...

Share this post


Link to post
Share on other sites
Programmer16    2321
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]

Share this post


Link to post
Share on other sites
izhbq412    204
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 ;)

Share this post


Link to post
Share on other sites
Rebooted    612
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this