I'm trying to make an implementation of a Vector in C (yes, I know, this has been done to death), generic across any types used. So far I have an implementation something like:
#define Vector(T) struct Vector_##T
// other routines, initialization, destruction, ...
// an example routine
#define DEFINE_VectorFirst(T) \
T VectorFirst_##T(Vector(T) vec) { \
return vec.data[0]; \
}
#define DEFINE_VECTOR(T) \
struct Vector_##T { \
T *data; \
size_t len; \
size_t capacity; \
}; \
DEFINE_VectorFirst(T)
// a few types for now
DEFINE_VECTOR(int)
DEFINE_VECTOR(double)
so I can, for example, declare a Vector(double) and then call VectorFirst_double on it. Ideally I'd like to not have to specify the type name every time, so I can use a generic:
#define GENERIC(F, T) Vector(T) : F##_##T
#define VectorFirst(v) \
_Generic((v), GENERIC(VectorFirst, int), GENERIC(VectorFirst, double))(v)
and now VectorFirst automatically calls the right version, but this loses the nice property that I can DEFINE_VECTOR in a bunch of different header files. In this way, the original version is "extensible", letting me make vectors of whatever structs I might declare elsewhere, but in the generic one I need to know all of the vector types I might ever need at one spot.
I could just use macros instead of functions for some things (#define VectorFirst(v) v.data[0] or the like) but it seems like this would make debugging annoying and maybe be slow for larger functions.
Are there any preprocessor techniques that can be used to restore this extensibility behavior and let me add new entries to a _Generic somewhere else? This is a small-scale test so I'm okay with whatever awful preprocessor hacks people know of.
#define GENERIC(F, T) Vector(T) : F##_##Twill have trouble with typelong long(types with a space in them). Your 1st approach apparently does not have that issue.typedefs, but that's still a fairly nasty gotcha.int*deserve testing too. (@JohnBollinger and hiding a pointer type in atypedefis an antipattern)