Я пытаюсь сделать что-то шаблонное в C:
Мне нужно создать 2d-векторную структуру с функциями для работы с ними, и мне нужно иметь их для типов int, unsigned int, float, double и, возможно, даже для других типов, которые поддерживают базовые математические функции.
Я мог бы написать весь код для каждого типа. Если я напишу ошибку в одном из них, я могу забыть исправить ошибку во всех остальных. Я делал это раньше в C ++ и просто использовал шаблоны, но теперь, когда я хочу это в C (C11) ... их нет.
Итак, я смотрю на макросы и вижу, что можно использовать тег ## для буквального использования переданного параметра макроса.
Вот код, который я пробовал:
#define DECLARE_VEC2(N, T) \
typedef struct { T x, y;} N; \
inline N *##N_new() { return malloc(sizeof(N));}
DECLARE_VEC2(vec2i, int);
DECLARE_VEC2(vec2f, float);
DECLARE_VEC2(vec2d, double);
Это не работает. ## N не заменяется на vec2i / vec2f / vec2d, а просто остается ## N или даже просто N. Компилятор не примет его, и когда я запускаю gcc с флагом -E в файле, я вижу, что препроцессор действительно не заменяет его.
Если, однако, я добавлю пробел между ## N и _new, препроцессор его заменит, но пробел тоже есть, что, очевидно, создает проблемы при его компиляции.
Однако, если я изменю имя функции на новое _ ## N, оно не только хорошо обрабатывает, но и работает без сбоев.
НО Я НЕ ХОЧУ ПОЗЖЕ!
Я создаю все свои структуры с функциональностью следующим образом: typename_function () и не хочу менять его из-за этой глупой проблемы.
Итак, вопрос: есть ли способ решить эту проблему?
Примечание: я также пробовал такие вещи, как добавление дополнительного параметра к макросу, содержащему подчеркивание, или даже объявление макроса внутри макроса с добавлением подчеркивания, но все они сталкиваются с одной и той же проблемой: существует необходимость в каком-то разделителе это заставляет препроцессор понять, что имя заканчивается перед подчеркиванием или тем, что стоит за ним.
Редактировать: как ни странно, при использовании чего-то вроде ## N ## _ new () препроцессор заменяет имя отлично, но затем не примет его с ошибками вроде:
error: pasting "*" and "vec2i" does not give a valid preprocessing token
inline N * ##N##_new() { return malloc(sizeof(N));}
хотя полученный код кажется правильным (gcc -E):
typedef struct { int x, y;} vec2i; inline vec2i *vec2i_new() { return malloc(sizeof(vec2i));};