Sign in to follow this  
Tree Penguin

Switching between variable types?

Recommended Posts

Tree Penguin    262
Couldn't think of a better thread title, what i mean is this: I have a function that is overloaded a few times with different variable/class types as arguments and i need a good way to switch between the types. Right now i do it like this:
switch(type){
case 0:
 myFunction((TYPE0 *)pointer);
 break;
case 1
 myFunction((TYPE1 *)pointer);
 break;
case 2:
 myFunction((TYPE2 *)pointer);
 break;
// etc..
}

// So i wonder if there is something like an array of types or something:

myFunction((type_array[type] *)pointer);

// or maybe the possibility to use a 'type' variable or something:
myFunction((mytype *)pointer);


Is there something like that or do i have to stick with my old way?

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by Tree Penguin
Is there something like that or do i have to stick with my old way?


two alternatives, dynamic polymorphism via type inheritance or static polymorphism via templates.

if your trying to create a factory method then there are other better alternatives to type switching aswell.

EDIT: Actually three alternatives, third being a combination of dynamic & static polymorphism.

[Edited by - snk_kid on November 23, 2004 10:36:17 AM]

Share this post


Link to post
Share on other sites
SiCrane    11839
I'm not entirely sure what you're trying to accomplish here, could you give a more concrete example?

However, judging just from the type switch it seems like you should make myFunction() a virtual function on the type of pointer.

Share this post


Link to post
Share on other sites
Enigma    1410
Having recently reread How To Ask Questions The Smart Way one of the entries seems like it may be appropriate here:
Quote:
Describe the goal, not the step

If you are trying to find out how to do something (as opposed to reporting a bug), begin by describing the goal. Only then describe the particular step towards it that you are blocked on.

Often, people who need technical help have a high-level goal in mind and get stuck on what they think is one particular path towards the goal. They come for help with the step, but don't realize that the path is wrong. It can take a lot of effort to get past this.

Stupid:

How do I get the color-picker on the FooDraw program to take a hexadecimal RGB value?
Smart:

I'm trying to replace the color table on an image with values of my choosing. Right now the only way I can see to do this is by editing each table slot, but I can't get FooDraw's color picker to take a hexadecimal RGB value.

The second version of the question is smart. It allows an answer that suggests a tool better suited to the task.


It may be that you do indeed need to do exactly what you are asking, but it may also be that there is a better way entirely. Cutting a problem down for posting on a forum is a good thing, but too much pruning can mean you're no longer dealing with the real problem.

Enigma

Share this post


Link to post
Share on other sites
snk_kid    1312
choice 1 dynamic polymorphism:


#include <iostream>

struct base_type {

virtual void do_foo() const = 0;
virtual ~base_type() {}

};

struct derived_type : public base_type {

void do_foo() const { std::cout << "derived1\n"; }

};

struct derived_type2 : public base_type {

void do_foo() const { std::cout << "derived2\n"; }

};

void do_do_foo(const base_type& b) {
b.do_foo();
}

int main() {
const derived_type1 d;
const derived_type2 d2;

do_do_foo(d);
do_do_foo(d2);
}



choice 2 static polymorphism:


#include <iostream>

struct foo {
void do_bar() const { std::cout << "foo\n"; }
};

struct bar {
void do_bar() const { std::cout << "bar\n"; }
};


template < typename Type >
void do_do_bar(const Type& b) {
b.do_bar();
}

int main() {

foo f;
bar b;

do_do_bar(f);
do_do_bar(b);
}

Share this post


Link to post
Share on other sites
petewood    819
If all the types are related in an inheritance hierarchy, put myFunction on the base class and make it virtual (or similar).


class Base {
virtual void myFunction();
};

class TYPE0 : public Base {
virtual void myFunction();
};
//etc.



So your code example would be replaced with

pointer->myFunction();


If they aren't related in a class hiearchy you can make your classes accept a Visitor object, which performs whatever you would have put in myFunction: (see VisitorPattern)
//derive from this to carry out what myFunction was doing
class Visitor {
virtual void Visit(TYPE0&) const {}
virtual void Visit(TYPE1&) const {}
virtual void Visit(TYPE2&) const {}
};

//derive all your types from this and implement Accept
class Visitable {
virtual void Accept(const Visitor&) = 0;
};




Usage:

class TYPE0 : public Visitable {
void Accept(const Visitor& visitor) {
visitor.Visit(*this);//magic happens here
}
};
//etc
class MyFunction : public Visitor {
virtual void Visit(TYPE0&) const;
virtual void Visit(TYPE1&) const;
virtual void Visit(TYPE2&) const;
}



Your original code becomes:

MyFunction visitor;
pointer->Accept(visitor);




Then you can add 'virtual functions' to the classes by deriving from Visitor instead of modifying the classes themselves.

edit: Thanks moderator[smile]

[Edited by - petewood on November 23, 2004 11:01:05 AM]

Share this post


Link to post
Share on other sites
Tree Penguin    262
Ok, i´ll explain myself a bit better, this is what i am trying to do:

In my application i have classes like Model, Camera, Texture, and more. With several functions the types of the pointers i pass are not important (managing lists, passing data to other components like etc.) so i cast them to type (void *) to avoid one version of the functions for every type i use.

My problem is that in some cases i might need to do something class specific
( in the gui for example when the user wants to edit something,
or i might want to get the 'name' variable of that object which exists in all classes i use )
but i got a (void *) pointer and an integer specifying the classtype.
What i do now is using a switch statement calling seperate functions for every class but as that's still pretty ugly and i still need to add a lot of functions when adding a class i wondered if there is any way to generalize it some more.

I guess i could make an 'Object' class which contains all non class-specific variables and all the switching between classes, but if there's another way i'd like to know it too.

I hope i am clear now, else please say so :).


EDIT: Thanks snk_kid! Thats what i needed (well, not exactly but i can use it instead).

Share this post


Link to post
Share on other sites
Enigma    1410
Sounds to me like templates will do exactly what you want:
// a generic function for any objects
template <typename TYPE>
void subFunction(TYPE object)
{
object.repaint();
}

// a specialisation for specific objects
template <>
void subFunction(Button button)
{
button.push();
}

// the main generic function for all objects
template <typename TYPE>
void genericFunction(TYPE object)
{
std::string objectName = object.name();
object.moveTo(10, 10);
subFunction(object);
}

Now calling genericFunction on a Label object will get the Label's name, move the Label and then repaint the Label, whereas calling genericFunction on a Button object will get the Button's name, move the Button and then push the Button, providing both Label and Button have the required member functions.

To try and put it more in the context you phrased it in:
Quote:
In my application i have classes like Model, Camera, Texture, and more. With several functions the types of the pointers i pass are not important (managing lists, passing data to other components like etc.) so i cast them to type (void *) to avoid one version of the functions for every type i use.

The templated approach means you only write one version of the function, but retain type checking and move type-dependant switching from runtime to compiletime.

Quote:
My problem is that in some cases i might need to do something class specific
( in the gui for example when the user wants to edit something,
or i might want to get the 'name' variable of that object which exists in all classes i use )
but i got a (void *) pointer and an integer specifying the classtype.

Break the specialised cases out into seperate functions and write template specialisations for them. It requires almost no extra code (just writing template a few times) and retains type checking and often makes the function clearer.

Quote:
What i do now is using a switch statement calling seperate functions for every class but as that's still pretty ugly and i still need to add a lot of functions when adding a class i wondered if there is any way to generalize it some more.

Hopefully what I've shown is applicable. Templates are there for generalisation. They are after all Generic Programming.

Hope that helps,

Enigma

Share this post


Link to post
Share on other sites
Pxtl    354
In short: learn C++. And before you say "but I know" - you're coding in C. Looks like you know your C pretty well, too. A good place to start is Bruce Eckel's "Thinking in C++" - its a free PDF available online.

Share this post


Link to post
Share on other sites
Telastyn    3777
I actually had almost the same exact implimentation, problem and solution 2-3 months ago. [though I put the switch statement in the function rather than before the function call]

I went with virtual inheritance for most cases, as [iirc] templates don't play nice with void pointers, requiring you to do the casting anyways. There still are a few places where the switch(type){} junk exists, but it is far lessened by only a few revisions.

Probably if I ever revamp that code the remaining instances would be replaced by templates.

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