Sign in to follow this  

type similar to union

This topic is 3630 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i need some kind of type that is like "union" that can store classes and when called returns the actual type that is currently set... for example class Base { union xtype { class1 A; class1 B; class1 C; } xtype U; void class_function(class1 a){} void class_function(class2 b){} void class_function(class3 c){} } main() { Base X; X.U = class1(somevalue); Base.class_function(X.U); // call the apropriate function } how can i do this? ive looked at boost::variant but i dont think it allows me to call function inside the same class as the variable... since i have to make a "visitor" class which cant access variables in the class (which i need to).

Share this post


Link to post
Share on other sites
Would using inheritance work for you instead?


__declspec(novtable) class Base
{
virtual void class_function() = 0;
};

class A : public virtual Base //, other base classes
{
virtual void class_function() {}
};

class B : public virtual Base //, etc
{
virtual void class_function() {}
};


main()
{
A a1;
Base *base = &a1;

base->class_function();
}

[Edited by - Nypyren on January 8, 2008 3:45:05 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Nypyren
Would using inheritance work for you instead?


im sorry i forgot to mention the regular types should also be used... i could make wrappers for all the types that i need though... but it seems like a quite ugly solution.. or?

EDIT:: Im using C++

Share this post


Link to post
Share on other sites
heh... well i guess soo... seems like i have a habit of simplifying my questions as much as possible...


i have a class which should store alot of objects/variables with different types and have "Set" functions for each type...

one way i could do this is to create on std::list<> for each type... but its a bit unpractical and ugly way to do it... also a bit slow where i have to decide which list to put new variables in...

what id like is a general type soo i can put all of them in the same list...

one way ive tried is to use boost::any... which works great except when i have to use "Set"... i have to first check which type it is than convert it to that type and call the appropriate "Set" function... which is kinda slow...

Share this post


Link to post
Share on other sites
Quote:
Original post by Dragon_Strike
Quote:
Original post by Nypyren
Would using inheritance work for you instead?


im sorry i forgot to mention the regular types should also be used... i could make wrappers for all the types that i need though... but it seems like a quite ugly solution.. or?

EDIT:: Im using C++


You'll have to make a separate class_function for every single type anyway, so making wrappers isn't THAT ugly.

Quote:
Original post by Antheus
Why?

It's pointless to talk about solution without knowing the problem it's trying to solve.


Actually, talking about it helps a person understand available options so that they can make better decisions for totally different problems in the future.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nypyren
Quote:
Original post by Dragon_Strike
Quote:
Original post by Nypyren
Would using inheritance work for you instead?


im sorry i forgot to mention the regular types should also be used... i could make wrappers for all the types that i need though... but it seems like a quite ugly solution.. or?

EDIT:: Im using C++


You'll have to make a separate class_function for every single type anyway, so making wrappers isn't THAT ugly.


well ill have to create a class initialization, constructor, variable and set function for every available type... thats for me 7 lines for each type... instead of only one (function)... but sure its acceptable...

but i think a solution with some kind of union type would make the code alot more readable and understandable...

EDIT:: and id also have to add one function each for adding it to the list since i have to know the type of the variable that is sent to the class to create and store the appropriate wrapper

Share this post


Link to post
Share on other sites
Quote:
Original post by Dragon_Strike
Quote:
Original post by Nypyren
Quote:
Original post by Dragon_Strike
Quote:
Original post by Nypyren
Would using inheritance work for you instead?


im sorry i forgot to mention the regular types should also be used... i could make wrappers for all the types that i need though... but it seems like a quite ugly solution.. or?

EDIT:: Im using C++


You'll have to make a separate class_function for every single type anyway, so making wrappers isn't THAT ugly.


well ill have to create a class initialization, constructor, variable and set function for every available type... thats for me 7 lines for each type... instead of only one (function)... but sure its acceptable...

but i think a solution with some kind of union type would make the code alot more readable and understandable...

EDIT:: and id also have to add one function each for adding it to the list since i have to know the type of the variable that is sent to the class to create and store the appropriate wrapper


You could use a template to avoid writing most of that more than once. Make a templated class that derives from Base and write any ctor/dtor/set functions you need, then derive from each specialization of the templated class in order to override class_function.

As for adding one to the list, you don't need any special functions.


main()
{
Wrapper<int> *foo = new Wrapper<int>(100);
Wrapper<std::string> *bar = new Wrapper<std::string>("hello, world!");

std::list<Base*> list1;

list1.push_back(foo);
list1.push_back(bar);

for (std::list<Base*>::iterator i = list1.start(); i != list1.end() ++i)
{
(*i)->class_function();
}

// Cleanup code left as an exercise to the reader.
}

Share this post


Link to post
Share on other sites
Here's a solution. I'm surprised boost does not offer anything to solve the problem though.

class Union{
struct UnionBase{
virtual void function_forward()=0;
//used for copy construction
virtual UnionBase *duplicate()=0;
virtual void *getValue()
virtual ~UnionBase(){};
};

template<typename T>
struct UnionChild: public UnionBase{
T m_value;

public:
UnionChild(T value):m_value(value);
void function_forward(){
function(value);
}
UnionBase *duplicate(){
new UnionChild(value);
}
void *getValue(){
return &m_value;
}
}
//this should probably be a smart pointer instead.
UnionBase *m_ptr;
public:
void call_function(){
m_ptr->function_forward();
}
template <typename T> T getValue(){
return *(T*)m_ptr->getValue()
}
template <typename T> void setValue(T val){
delete m_ptr;
m_ptr=new UnionChild<T>(val);
}

}



Share this post


Link to post
Share on other sites
Quote:
Original post by Dragon_Strike
Quote:
Original post by King Mir
Is the type X.U compile time constant?


im unsure what you mean...

Is the type of value a "Union" holds determinable at compile time? or can it depend on runtime input?

Cause if it is, it is a simpler problem.

Share this post


Link to post
Share on other sites
Quote:
Original post by King Mir
Quote:
Original post by Dragon_Strike
Quote:
Original post by King Mir
Is the type X.U compile time constant?


im unsure what you mean...

Is the type of value a "Union" holds determinable at compile time?

Cause if it is, it is a simpler problem.


well what types of values it will hold can be determined... however which type that will actually be used cant be decided until the union is acutally set... ?

i dont rly get where u going... what are u thinking of?

Share this post


Link to post
Share on other sites
Quote:

You could use a template to avoid writing most of that more than once. Make a templated class that derives from Base and write any ctor/dtor/set functions you need, then derive from each specialization of the templated class in order to override class_function.

As for adding one to the list, you don't need any special functions.


main()
{
Wrapper<int> *foo = new Wrapper<int>(100);
Wrapper<std::string> *bar = new Wrapper<std::string>("hello, world!");

std::list<Base*> list1;

list1.push_back(foo);
list1.push_back(bar);

for (std::list<Base*>::iterator i = list1.start(); i != list1.end() ++i)
{
(*i)->class_function();
}

// Cleanup code left as an exercise to the reader.
}


thx.. that solved it for me...


class Param
{
public:
Param() : handle(0) {}
Param(D3DXHANDLE _handle): handle(_handle){}
D3DXHANDLE handle;
virtual HRESULT SetParam(CEffect* effect) = 0;
};

template <class T>
class ParamType : public Param
{
public:
ParamType() : Param(0), value(0){}
ParamType(D3DXHANDLE _handle, T _value) : Param(_handle), value(_value){}
T value;
HRESULT SetParam(CEffect* effect) { return effect->SetParam(handle, value);}
};


Share this post


Link to post
Share on other sites
Quote:
Original post by Dragon_Strike
i have a class which should store alot of objects/variables with different types and have "Set" functions for each type...
Some more context would be useful. Are these variables in a scripting language? Objects in a game? UI components? What is the high-level problem you are trying to solve? From what you have said, it sounds like boost::variant is a suitable candidate, but without more information I can't properly fit it to your problem (if it is a suitable solution).

Σnigma

Share this post


Link to post
Share on other sites
Quote:
Original post by Enigma
Quote:
Original post by Dragon_Strike
i have a class which should store alot of objects/variables with different types and have "Set" functions for each type...
Some more context would be useful. Are these variables in a scripting language? Objects in a game? UI components? What is the high-level problem you are trying to solve? From what you have said, it sounds like boost::variant is a suitable candidate, but without more information I can't properly fit it to your problem (if it is a suitable solution).

Σnigma


im very interested in how boost::variant could solve a problem like this...

they are simple int,float etc.. variables and DirectX "objects" or what you would call them...

what information is it that you need?

Share this post


Link to post
Share on other sites
Quote:
Original post by Dragon_Strike
Quote:
Original post by King Mir
Quote:
Original post by Dragon_Strike
Quote:
Original post by King Mir
Is the type X.U compile time constant?


im unsure what you mean...

Is the type of value a "Union" holds determinable at compile time?

Cause if it is, it is a simpler problem.


well what types of values it will hold can be determined... however which type that will actually be used cant be decided until the union is acutally set... ?

i dont rly get where u going... what are u thinking of?

So no then.

If it were, you could use some kind of template container that holds a list of unrelated types. Then you'd use recursion to apply the function to every type. Or there may be some other solution. But it would change the problem dramatically.

Share this post


Link to post
Share on other sites
Your post eight seconds before mine gave me the necessary context. Untested:

class SetParamVisitor
:
public boost::static_visitor< HRESULT >
{

public:

SetParamVisitor(CEffect & effect, D3DXHANDLE handle)
:
effect_(effect),
handle_(handle)
{
}

template < typename type >
HRESULT operator()(type const & value) const
{
return effect_.SetParam(handle_, value);
}

private:

CEffect & effect_;
D3DXHANDLE handle_;

};

class Param
{

public:

template < typename type >
Param(D3DXHANDLE handle, type const & value)
:
handle_(handle)
value_(value)
{
}

// no null check, so you should really be using a
// reference, not a pointer
HRESULT SetParam(CEffect & effect) const
{
return boost::apply_visitor(SetParamVisitor(effect, handle_), value_);
}

private:

D3DXHANDLE handle_;
boost::variant< types > value_;

};

In this situation this doesn't really gain you anything over the inheritance based solution though.

Σnigma

Share this post


Link to post
Share on other sites
Quote:
Original post by Enigma
Your post eight seconds before mine gave me the necessary context. Untested:

*** Source Snippet Removed ***
In this situation this doesn't really gain you anything over the inheritance based solution though.

Σnigma


no but i finally understood how variants can be used... thx alot

Share this post


Link to post
Share on other sites

This topic is 3630 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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