Last active
March 9, 2017 18:27
-
-
Save shintakezou/82c4601284dc05fd26f8 to your computer and use it in GitHub Desktop.
C11 _Generic basic test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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