Then you can use them with the #include code generation trick like this:
#include <stdlib.h>
#define ARRAY_ELEMENT_TYPE int
#include "array_template_impl.h"
#define ARRAY_ELEMENT_TYPE float
#include "array_template_impl.h"
int main() {
array_int *ai = array_int_create(0);
array_float *af = array_float_create(0);
for(int i = 0; i < 10; ++i) {
array_int_push_back(ai, i);
array_float_push_back(af, i * 0.3f);
}
array_int_free(ai);
array_float_free(af);
return 0;
}
(In practice you might want even more indirection files: Put #define and #include in array_int.c. and array_float.c, and create also array_int.h, array_float.h and array_template_decl.h with just the usual declarations.)
This is a cool technique, but I tried compiling the first block of code you posted (with ARRAY_ELEMENT_TYPE being defined to be int* ) and got "error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token" from gcc 6.2 using the flags that to3m specified in one of the parent posts posts. Is there a special trick I can use to get that to work?
Actually now that I think about it, it might be better to just make a typedef and then you can go back to using the same name everywhere. I think that would solve the problem.
This technique seems to take care of the bulk of the use of templates in C++, i.e. simple data structure or function definitions. But it's not a full replacement, because I don't think you can use this to do things like pass an integer to one of these templates, then have that template use another template and pass a calculation based on that number to the other template like you could do in C++. Something like this:
It for sure not quite the same as C++ templates, but if you can tolerate crazy things you can do a lot with the preprocessor. See http://www.boost.org/libs/preprocessor/ (supports both C++ and C).
It might almost work, but you'd need to pull out some more tricks I'm sure. Maybe BOOST_PP_DIV(Y,2) would help. In practice I'd prefer something sane. :)