Does C have generics?
Take the following C program:
#include <stdio.h>
int main() {
char* x = "foo";
printf("Type of x is: %s\n", _Generic(x, char*: "string", int: "int"));
return 0;
}
It produces:
$ clang generic.c
$ ./a.out
Type of x is: string
The new expression in this program is _Generic(x, char*: "string", int: "int")
, which we see evaluates to "string"
. The _Generic(...)
expression form is new in C11. It is evaluated at compile-time based on the type of its first argument, in this case x
of type char*
. The following char*: "string", int: "int"
is an association list, mapping types to expressions. The compiler selects the expression associated with the type of the first argument; thus in this case it selects "string"
and the program is transformed at compile-time to:
printf("Type of x is: %s\n", "string");
The _Generic(...)
expression can be used for overloaded functions. For example, a max
function which selects a concrete implementation depending on the type of the arguments:
#include <stdio.h>
#include <string.h>
int max_int(int a, int b) { return (a < b ? b : a); }
char* max_string(char* a, char* b) { return (strcmp(a, b) < 0 ? b : a); }
#define max(X, Y) ((_Generic((X), int: max_int, char*: max_string))(X,Y))
int main() {
int ix = 5; int iy = 6;
printf("Max of %d and %d is: %d\n", ix, iy, max(ix, iy));
char* sx = "foo"; char* sy = "bar";
printf("Max of %s and %s is: %s\n", sx, sy, max(sx, sy));
return 0;
}
Despite the name, this is not generics! A true “generics in C” feature would allow you to define:
T max<T>(T a, T b) { return (a < b ? b : a); }
In _Generic
, all concrete implementations must be manually written, rather than generated through type-instantiation. More importantly, in _Generic
, the set of max
functions is closed; to add a new max
function for a new type, one must have access to the definition of max
. In a true generics feature, max
can be generated for any user type with <
defined on it.
This page copyright James Fisher 2017. Content is not associated with my employer.