Псевдо-дженерики в C
Мне нужно реализовать некоторые методы, которые делают вещи с различными типами массивов чисел. Обычно я использую generics для этой работы, но поскольку C не предоставляет их, я теперь пытаюсь имитировать их с помощью макросов.
Вот пример того, что я пытаюсь сделать:
#ifndef TYPE #define TYPE int #endif TYPE get_minimum_##TYPE (TYPE * nums, int len){ TYPE min = nums[0]; for (int i = 1; i < len; i++) { if (nums[i] < min) { min = nums[i]; } } return min; }
Однако это не будет компилироваться. Сообщение об ошибке clang:
- Как мне адресовать непроверенные предупреждения о броске?
- Что такое SuppressWarnings («unchecked») в Java?
- Общий метод с несколькими ограничениями
- Общее ограничение для сопоставления числовых типов
- Что означает список В java generics?
error: expected ‘;’ после декларатора верхнего уровня
Есть ли способ сделать это в C? Или мне нужно реализовать это для каждого типа вручную?
- Общий подclass NSOperation теряет функциональность NSOperation
- Java generics - почему «extends T» разрешен, но не «реализует T»?
- Generics компилируется и запускается в Eclipse, но не компилируется в javac
- Как удалить элементы из общего списка во время итерации по нему?
- Общий TryParse
- Почему я не могу использовать аргумент типа в параметре типа с несколькими ограничениями?
- Не удается создать массив LinkedLists в Java ...?
- Как работает Gson TypeToken?
Вы можете сделать что-то подобное в файле заголовка:
// // generic.h // #define TOKENPASTE(x, y) x ## y #define GET_MINIMUM(T) TOKENPASTE(get_minimum_, T) TYPE GET_MINIMUM (TYPE) (TYPE * nums, size_t len){ TYPE min = nums[0]; for (size_t i = 1; i < len; i++) { if (nums[i] < min) { min = nums[i]; } } return min; }
а затем #include
его в исходный файл для каждого требуемого типа, например:
// // generic.c // #define TYPE int #include "generic.h" #undef TYPE #define TYPE float #include "generic.h" #undef TYPE
Вы можете проверить это, запустив его через препроцессор:
$ gcc -E generic.c int get_minimum_int (int * nums, size_t len){ int min = nums[0]; for (size_t i = 1; i < len; i++) { if (nums[i] < min) { min = nums[i]; } } return min; } float get_minimum_float (float * nums, size_t len){ float min = nums[0]; for (size_t i = 1; i < len; i++) { if (nums[i] < min) { min = nums[i]; } } return min; }
Фактически, лучше всего вы можете определить макрос, который будет генерировать функцию для данного типа.
#define define_get_minimum(T) \ T get_minimum_##T(T* nums, int len){ \ T min = nums[0]; \ for (int i = 1; i < len; i++) { \ if (nums[i] < min) { \ min = nums[i]; \ } \ } \ return min; \ }
Затем вы можете вызвать этот макрос, чтобы определить необходимые вам специализации (с помощью шаблона C ++ аналогичная операция выполняется автоматически компилятором).
define_get_minimum(int) define_get_minimum(double) define_get_minimum(float)
Другое дело, что компилятор C ++ делает автоматически, вывести перегруженную функцию, в которой вы нуждаетесь. Вы не можете иметь это в C, поэтому вам придется сказать, что вы используете его специализацию. Вы можете имитировать синтаксис типа шаблона для вашей функции со следующим макросом (C ++ <>
просто заменяется на ()
):
#define get_minimum(T) get_minimum_##T
Затем вы можете назвать это следующим образом:
int main() { // Define arr as char* array... // Do stuff... int res = get_minimum(int)(arr, 3); }
Я не тестировал этот код, но он должен работать.
Вы также можете использовать указатели функций (Массив указателей функций), кроме оператора switch, и передать аргумент коммутатора в качестве индекса в массив.