Specifying data types inside functions

N

No One

Here is my problem:

I have a certain set of well-defined manipulations that I have to apply
to different types of data. In all cases the manipulations are exactly the
same, and are to be performed on the different types of data. Currently I
have a collection of functions that do exactly the same - the only
difference between them is the type of data they act on. Let me present a
toy example:

I have the following two data types:

typedef struct { typedef struct {
int x ; int x ;
int y ; char * p ;
char * s ; } data_two ;
} data_one ;

Thus, I know that both data_one and data_two have an integer field, x.
The remaining fields can be arbitrarily different.

I want to have a function that takes as an argument a pointer to one of
those structures, increments the x member and returns a pointer to the
same structure. Currently I have two functions:

data_one * f_one(data_one * data) data_two * f_two(data_two * data)
{ {
data->x += 1 ; data->x += 1 ;

return data ; return data ;
} }

The bodies of the functions are identical - which is a waste.
I'd rather use a single function, with a prototype similar to:

void * f(data_type type, void * data)

where "type" would specify the actual type of the data we are dealing with.

Can something along these lines be done? Please remember that the above
is just a toy example.
 
M

Malcolm

No One said:
I have the following two data types:

typedef struct { typedef struct {
int x ; int x ;
int y ; char * p ;
char * s ; } data_two ;
} data_one ;

I'd rather use a single function, with a prototype similar to:

void * f(data_type type, void * data)

where "type" would specify the actual type of the data we are
dealing with.
You very rapidly get into a murky area of the C standard here. There are
some guarantees about structure layout in memory, but it is generally not a
good idea to use extendable structures or to try to convert one type of
structure to another.

If two structures have a common header then do this

struct common
{
int x;
...
};

typedef struct
{
struct common header;
...
}data_one;

typedef struct
{
struct common header;
...
} data_two;

Now when you write f

void f(data_type type, void *data)
{
data_one *data1;
data_two *data2;
switch(type)
{
case 1:
data1 = data;
foo( data1->header);
break;
case 2:
data2 = data;
foo(data2->header);
break;
}
}

Theoretically you could cast data to a struct common * directly, but this is
asking for trouble. For instance, if someone inserts another member at the
beginning of one of the structs the code will break without warning.
 
P

Peter Ammon

No said:
Here is my problem:

I have a certain set of well-defined manipulations that I have to apply
to different types of data. In all cases the manipulations are exactly the
same, and are to be performed on the different types of data. Currently I
have a collection of functions that do exactly the same - the only
difference between them is the type of data they act on. Let me present a
toy example:

I have the following two data types:

typedef struct { typedef struct {
int x ; int x ;
int y ; char * p ;
char * s ; } data_two ;
} data_one ;

Thus, I know that both data_one and data_two have an integer field, x.
The remaining fields can be arbitrarily different.

I want to have a function that takes as an argument a pointer to one of
those structures, increments the x member and returns a pointer to the
same structure. Currently I have two functions:

data_one * f_one(data_one * data) data_two * f_two(data_two * data)
{ {
data->x += 1 ; data->x += 1 ;

return data ; return data ;
} }

The bodies of the functions are identical - which is a waste.
I'd rather use a single function, with a prototype similar to:

void * f(data_type type, void * data)

where "type" would specify the actual type of the data we are dealing with.

Can something along these lines be done? Please remember that the above
is just a toy example.

You can use the preprocessor.

#define func(type) type* f_##type (type* data) {\
data->x+=1; \
return data; \
}

func(data_one)
func(data_two)


With C++, you'd use templates.

-Peter
 
N

No One

You very rapidly get into a murky area of the C standard here. There are
some guarantees about structure layout in memory, but it is generally not
a good idea to use extendable structures or to try to convert one type of
structure to another.

If two structures have a common header then do this

struct common
{
int x;
...
};

typedef struct
{
struct common header;
...
}data_one;

typedef struct
{
struct common header;
...
} data_two;

Now when you write f

void f(data_type type, void *data)
{
data_one *data1;
data_two *data2;
switch(type)
{
case 1:
data1 = data;
foo( data1->header);
break;
case 2:
data2 = data;
foo(data2->header);
break;
}
}
}
Theoretically you could cast data to a struct common * directly, but this
is asking for trouble. For instance, if someone inserts another member at
the beginning of one of the structs the code will break without warning.

Thanks for your feedback. The solution that you propose is similar to
what I am using. My actual problem is even worse than I presented, for the
common fields might not always be the first ones in the structures :-( It
seems to me that I am stuck with ugly code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top