Sign in to follow this  
timaer

[solved]Can C language have template?

Recommended Posts

I'm using C to make a little game,with the project getting more huge,I found something I can't use C to implement. I need the function could take a parameter,which can be any type,including struct type.But I found I could't let the void* pointer take the struct type. Can any guys tell me how can I do to realize the feature such like template in C++? Thanks in advance. [Edited by - timaer on March 27, 2006 7:01:06 AM]

Share this post


Link to post
Share on other sites
In C your best bet is to use macros. If you want templates you will have to switch to C++. Is there any reason why you are using plain C?

Share this post


Link to post
Share on other sites
Hey bud,

All i can suggest is that you just go ahead and write out a function for each of the types. This is what C++ replaces the need to do, with templates.

Hope that helps,

Dave

Share this post


Link to post
Share on other sites
thanks Tjaalie and twanvl,could you give more detail about how to implement the function with macros?

and Hi,Dave,your idea is not bad ,if so,I have so many C function to be modified just becouse I need the feature which template can provide.I really hope I could rebuild my project and use C++ to do so,but I'm in a hurry to work the game out ,so I've to do it with C ;(

Share this post


Link to post
Share on other sites
EG:



#define TEMPLATE_COMPLEX_DECLARE( type ) \
typedef struct{ \
type real; \
type imaginary; \
}Complex##type;

TEMPLATE_COMPLEX_DECLARE( float );
TEMPLATE_COMPLEX_DECLARE( double );

int main( int argc, char **argv )
{
Complexdouble d;
d.real = 0.0f;
Complexfloat f;
f.imaginary = 1.0f;




[EDIT] arrgh, the source/code tags keep eating my "\" slashes...

Share this post


Link to post
Share on other sites
Quote:
Original post by Dave
Quote:
Original post by rip-off
EG:

*** Source Snippet Removed ***


That's horrid :P

Dave


Thats templates in c :P

c++ templates arent too much better to look at, mind you, until you're used to them

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
EG:

*** Source Snippet Removed ***

[EDIT] arrgh, the source/code tags keep eating my "\" slashes...



Hi,rip-off,you code looks nice,but still makes me a little confused(you know I'm bud;)

if I want to have a function like

int Animate_BOB(ANY_TYPE bob)

the ANY_TYPE could be monster or player struct type etc..

Could you give me the complete macro code for implementing this? ;)Thanks.

Share this post


Link to post
Share on other sites
Hmm, i suppose it would go like this:



#define DECLARE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob );

#define DEFINE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
}

// So in a header file(s), you ca just say:

DECLARE_ANIMATE_BOB( Type1 );
DECLARE_ANIMATE_BOB( Type2 );

// And in the corresponding source file(s)

DEFINE_ANIMATE_BOB( Type1 );
DEFINE_ANIMATE_BOB( Type2 );




And you should be able to use the functions like so:

int result1 = Animate_BOBType1( bobType1 );
int result2 = Animate_BOBType2( bobType2 );

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Hmm, i suppose it would go like this:

*** Source Snippet Removed ***

And you should be able to use the functions like so:

int result1 = Animate_BOBType1( bobType1 );
int result2 = Animate_BOBType2( bobType2 );




I suppose that's just what I need,anyway need some time to digest .Well,I'm a little sleepy,I'll study your code very hard tomorrow.Thank you so much , rip-off.And now I'd rather go to bed,Good night.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off

#define DECLARE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob );

#define DEFINE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
}

// So in a header file(s), you ca just say:

DECLARE_ANIMATE_BOB( Type1 );
DECLARE_ANIMATE_BOB( Type2 );

// And in the corresponding source file(s)

DEFINE_ANIMATE_BOB( Type1 ); // you wouldn't put semicolons here would you?
DEFINE_ANIMATE_BOB( Type2 );

would that expand to this:

int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
};



Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off

#define DECLARE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob );

#define DEFINE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
}

// So in a header file(s), you ca just say:

DECLARE_ANIMATE_BOB( Type1 );
DECLARE_ANIMATE_BOB( Type2 );

// And in the corresponding source file(s)

DEFINE_ANIMATE_BOB( Type1 ); // you wouldn't put semicolons here would you?
DEFINE_ANIMATE_BOB( Type2 );

would that expand to this:

int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
};



Share this post


Link to post
Share on other sites
Quote:
Quote:
Original post by Alpha_ProgDes

DEFINE_ANIMATE_BOB( Type1 ); // you wouldn't put semicolons here would you?
DEFINE_ANIMATE_BOB( Type2 );[/code]

would that expand to this:

int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
};


The extra semicolons are compilable apparently...

But yeah, I am just too used to putting them in.

It is better to omit them in the prototype, so this code won't compile:

DECLARE_ANIMATE_BOB( type ) // no semicolon

So a revised version:


#define DECLARE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob )

#define DEFINE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
}

DECLARE_ANIMATE_BOB( int );
DEFINE_ANIMATE_BOB( int );




Unfourtunatly DEFINE_ANIMATE_BOB( int ) will still compile with out a semicolon, but I can't see a way around that right now...

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Quote:
Quote:
Original post by Alpha_ProgDes

DEFINE_ANIMATE_BOB( Type1 ); // you wouldn't put semicolons here would you?
DEFINE_ANIMATE_BOB( Type2 );[/code]

would that expand to this:

int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
};


The extra semicolons are compilable apparently...

But yeah, I am just too used to putting them in.

It is better to omit them in the prototype, so this code won't compile:

DECLARE_ANIMATE_BOB( type ) // no semicolon

So a revised version:

*** Source Snippet Removed ***

Unfourtunatly DEFINE_ANIMATE_BOB( int ) will still compile with out a semicolon, but I can't see a way around that right now...


I don't see a way for that to truly need a semi on the end.

The only way to require a semi is either like the above on a function declaration or something like this on a statement(s):

#define MY_MACRO(x) do { do_stuff_with((x)); } while (false)

or:

#define MY_MACRO(x) if (true) do_stuff_with((x)); else

But the second one is kinda risky.

But really, I see 0 ways for a function declaration to work o_O.

EDIT: Source is messing with my '\'.
EDIT2: Well, if you ABOSUTELY WANT a semi, you must add a '}', too:

#define DEFINE_ANIMATE_BOB(type)
int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue()

//And
DEFINE_ANIMATE_BOB(int);}

[grin]

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
EG:

*** Source Snippet Removed ***

[EDIT] arrgh, the source/code tags keep eating my "\" slashes...


I'm pretty sure C already has a complex number type.


#include <complex.h>

int main()
{
complex double number = 42.0+1.0i;
}





Edit: Well, apparently imaginary constants aren't standard, but the complex type itself is.

Share this post


Link to post
Share on other sites
There is one way... but its so ugly I wouldn't do it.

Basically so the equivalent of:



void foo()
{
// stuff
}
void foo(); // not actaully required, but allowed

// IE

#define DEFINE_ANIMATE_BOB( type ) \
int Animate_BOB##type( type bob ) \
{ \
do_stuff_with( bob ); \
return somevalue(); \
}\
int Animate_BOB##type( type bob )





We insert a redundant declaration without a semicolon. It forces you to put in a semicolon, but its not pretty nor does it give any clue as to whats going on...


Quote:
Original post by smart_idiot
Quote:
Original post by rip-off
EG:

*** Source Snippet Removed ***

[EDIT] arrgh, the source/code tags keep eating my "\" slashes...


I'm pretty sure C already has a complex number type.

*** Source Snippet Removed ***


It was just an example of a POD that could be meaningfully templated. The OP already had some function / type in mind for templating...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
the complex type is in the standar of C.

Share this post


Link to post
Share on other sites
Why would you be bothered about it compiling without a semicolon? Okay, so it lets you be lazy, but as long as it will compile with the semicolon there then I don't see why it's a problem ...

Share this post


Link to post
Share on other sites
Quote:
Original post by Bob Janova
Why would you be bothered about it compiling without a semicolon?


Because the extra semicolon could break things like if/else statements if you don't take care of it.

Share this post


Link to post
Share on other sites
1) Complex floating point numbers were added in C99, most compilers support the older C89 standard.

2) It sounds like you're trying to shoe horn a C++ solution into C. Don't do that. Often, good C++ is bad C and good C is bad C++. I prefer C for what I do, but that's because I've decided C is the right tool for the job (everything I need, nothing I don't, and dealing with an established C code base). If I needed templates as a fundamental part of the design, then C would be one of the first languages I'd rule out as "the right tool".

3) I think lcc-win32 offers templates as an extension. Non-portable, but that may or may not be an issue.

4) The usual C solution is one function for each type (see OpenGL) or a union of structs with a type paramter:

typedef union {
struct { int type; } info;
struct { int type; double data; } type_double;
struct { int type; float data; } type_float;
/* etc... */
} MyTemplateType;

enum {
MY_TEMPLATE_DOUBLE,
MY_TEMPLATE_FLOAT,
/* etc... */
}

int foo(MyTemplateType *t) {
switch(t->info.type) {
case MY_TEMPLATE_DOUBLE: {
/* Do stuff with t->type_double.data */
return 0;
}
case MY_TEMPLATE_FLOAT: {
/* Do stuff with t->type_float.data */
return 0;
}
default: { /* Error */ return -1; }
}
}


If you find that too cumbersome, you just found one reason why C++ exists.

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