I wrote the following code in plain C:
#define _cat(A, B) A ## _ ## B
#define cat(A, B) _cat(A, B)
#define plus(A, B) cat(cat(plus,__typeof__(A)),__typeof__(B))(A, B)
int main(int argc, const char * argv[])
{
double x = 1, y = 0.5;
double r = plus(x, y);
printf("%lf",r);
return 0;
}
Here, I would like the macro plus
to be expanded becoming a function name which contains the types of the parameters. In this example I would like it to expand the following way
double r = plus(x, y)
...
/* First becomes*/
double r = cat(cat(plus,double),double)(x, y)
...
/* Then */
double r = cat(plus_double,double)(x, y)
...
/* And finally */
double r = plus_double_double(x, y)
However all I got from the preprocessor is
double r = plus___typeof__(x)___typeof(y)(x,y)
and gcc will obviously refuse to compile.
Now, I know that typeof evaluates at compile-time and it is my understanding that a macro is only prevented from being evaluated when it is contained in second macro which directly involves the stringify #
and the concatenation ##
tokens (here's the reason why I split cat
in the way you see). If this is right, why doesn't __typeof__(x)
get evaluated to double by the preprocessor? Seems to me that the behaviour should be perfectly clear at build time. Shouldn't __typeof__(x)
evaluate to double
before even going in _cat
?
I searched and searched but I couldn't find anything... Am I doing something really really stupid?
I'm running Mac OS X Mountain Lion but I'm mostly interested in getting it work on any POSIX platform.
The __typeof__ operator returns the type of its argument, which can be an expression or a type. The language feature provides a way to derive the type from an expression. Given an expression e , __typeof__(e) can be used anywhere a type name is needed, for example in a declaration or in a cast.
The typeof keyword is a new extension to the C language. The Oracle Developer Studio C compiler accepts constructs with typeof wherever a typedef name is accepted, including the following syntactic categories: Declarations. Parameter type lists and return types in a function declarator.
The number-sign or "stringizing" operator (#) converts macro parameters to string literals without expanding the parameter definition. It's used only with macros that take arguments.
The reason this does not work is typeof is not a macro but a reserved word in the gcc's dialect of C and is thus handled after the preprocessor has finished its work. A good analogy would be the sizeof operator which is not a macro either and is not expanded by the preprocessor. To do (approximately) what you want (pick a different function based on the type of the arguments) try the _Generic construct (new in C11)
Macro expansion occurs before C token analysis (see https://stackoverflow.com/a/1479972/1583175 for a diagram of the phases of translation)
The macro preprocessor is unaware of the type information -- it merely does text processing
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With