I have a list of data types (STANDARD_TYPES). I would like to automatically (using X macros) create functions that would convert from one of those type to another.
I have the following code:
#define STANDARD_TYPES(macro) \
macro(char) \
macro(uchar) \
macro(schar) \
macro(short) \
macro(ushort) \
macro(int) \
macro(uint) \
macro(long) \
macro(ulong) \
macro(longlong) \
macro(ulonglong) \
macro(float) \
macro(double) \
macro(longdouble)
#define Y(to_type, from_type) \
case TYPE_##from_type: \
((struct result_##to_type *)result)->value = \
(to_type)((struct result_##from_type *)result)->value; \
break;
#define X(to_type) \
void convert_to_##to_type(struct result *result) \
{ \
switch (result->type) { \
Y(to_type, long) \
} \
\
return result; \
}
STANDARD_TYPES(X)
#undef X
#undef Y
struct result_X is generated for every type and looks like:
struct result {
enum type type;
};
struct result_char {
enum type type;
char value;
};
struct result_long {
enum type type;
long value;
};
With the above code example I can generate functions to convert from char data type to any other data type. For example, long output for the above code example would be:
void convert_to_long(struct result *result)
{
switch (result->type) {
case TYPE_char:
((struct result_long *)result)->value = (long)((struct result_char *)result)->value;
break;
}
}
With what can I replace Y(to_type, char) code or more parts of the code to make it generate conversion functions between all defined data types?
EDIT:
enum type {
TYPE_char,
TYPE_uchar,
TYPE_schar,
...
TYPE_long,
...
};
EDIT2:
To clear up some things I shall explain briefly what my code is trying to accomplish. On the user side, that is whoever is using my code, they are executing some math operations and when done they write the result to the struct result *result along with the type of the result and the value.
My code shall then convert value of the struct result *result from the type contained in struct result *result to the requested type which can be any of the standard types.
void convert_result(struct result *result, enum type new_type)
{
switch (new_type) {
case TYPE_char:
convert_to_char(result);
break;
...
case TYPE_long:
convert_to_long(result);
break;
};
I do not think there is a way to get the desired behavior of applying the X Macro within itself, since recursive macro replacement is suppressed by C 2018 6.10.3.4 2. However, if you define two X Macros, this can be done:
This is replaced by (with manual formatting added for readability):
To give this code behavior defined by the C standard, you could define a union containing all the
resultstructures, so that C 2018 6.5.2.3 6 would apply.1 However, it may be nicer simply to define one structure containing a union and rewrite the code to match:For example:
Footnote
1 C 2018 6.5.2.3 6 says:
Also relevant is C 2018 67.2.1 16: