Skip to content

Instantly share code, notes, and snippets.

@shintakezou
Last active March 9, 2017 18:27
Show Gist options
  • Save shintakezou/82c4601284dc05fd26f8 to your computer and use it in GitHub Desktop.
Save shintakezou/82c4601284dc05fd26f8 to your computer and use it in GitHub Desktop.
C11 _Generic basic test
#include <stdio.h>
typedef struct {
double x;
double y;
} vec2d;
#define sum(X, Y) _Generic((X), \
int: sum2l((X), (Y)), \
long: sum2l((X), (Y)), \
double: sum2d((X), (Y)), \
float: sum2d((X), (Y)))
// this won't work - because it's wrong
#define sumxWrong(X, Y) _Generic((X), \
int: sum2l((X), (Y)), \
long: sum2l((X), (Y)), \
double: sum2d((X), (Y)), \
float: sum2d((X), (Y)), \
vec2d: sum2v((X), (Y)))
// this works (thanks to Michael Stoffregen who suggested the right way)
#define sumx(X, Y) _Generic((X), \
int: sum2l, \
long: sum2l, \
double: sum2d, \
float: sum2d, \
vec2d: sum2v)((X), (Y))
long sum2l(long x, long y)
{
return x + y/2;
}
double sum2d(double x, double y)
{
return x + y/2.0;
}
vec2d sum2v(vec2d a, vec2d b)
{
vec2d r = {a.x + b.x, (a.y + b.y)/2.0};
return r;
}
int main(void)
{
printf("%ld %lf\n", sum(5, 3), sum(5.0, 3));
vec2d a = {1.0, 2.5};
vec2d b = {3.0, 3.5};
// calling explicitly the right function: no overloading
vec2d r = sum2v(a, b);
printf("%lf %lf\n", r.x, r.y);
// let's try with "genericity"
r = sumx(a, b);
printf("%lf %lf\n", r.x, r.y);
/* the following does not work in both compiler: it seems both would choose sum2l, instead of sum2v.
part of clang error output:
generic.c:57:9: error: passing 'vec2d' to parameter of incompatible type 'long';
r = sumx(a, b);
^~~~~~~~~~
part of gcc error output:
generic.c:57:9: note: in expansion of macro ‘sumx’
r = sumx(a, b);
^
generic.c:24:6: note: expected ‘long int’ but argument is of type ‘vec2d’
*/
//r = sumxWrong(a, b); // it was sumx, which now works fine ^_^
/*
the following does not work neither.
In both cases I would expect it would choose sum2l; but...
gcc:
generic.c:80:15: note: in expansion of macro ‘sumx’
int res = sumx(1, 2);
^
generic.c:34:7: note: expected ‘vec2d’ but argument is of type ‘int’
vec2d sum2v(vec2d a, vec2d b)
^
clang:
generic.c:89:15: error: passing 'int' to parameter of incompatible type 'vec2d';
int res = sumx(1, 2);
^~~~~~~~~~
*/
//int res = sumxWrong(1, 2);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment