Псевдо-дженерики в 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:

error: expected ‘;’ после декларатора верхнего уровня

Есть ли способ сделать это в C? Или мне нужно реализовать это для каждого типа вручную?

Вы можете сделать что-то подобное в файле заголовка:

 // // 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, и передать аргумент коммутатора в качестве индекса в массив.

  • Объяснение принципа get-put
  • Кастинг для общего типа в Java не вызывает ClassCastException?
  • Общий ролик .NET Casting
  • Что означает (угловые скобки) в Java?
  • Разница между типичным типом и подстановочным типом
  • Общий код C # и оператор Plus
  • Общие ограничения, где T: struct и где T: class
  • получение типа T из IEnumerable
  • Синтаксис и использование примера _Generic в C11
  • Как решить Operator '! =' Нельзя применить к операндам типа T и T
  • Почему Func неоднозначен с Func <IEnumerable >?
  • Interesting Posts

    Обнаружить конец ScrollView

    Как программно отключить мобильный Android?

    Преобразование формата строки в datetime в мм / дд / гггг

    Как добавить события в элементы управления, созданные во время выполнения в Excel с помощью VBA

    Как я могу избавиться от помощника клипа Microsoft «Clippy»?

    Советы по поиску моего похищенного компьютера?

    Аутентификация со старым паролем больше не поддерживается, используйте пароли типа 4.1

    Настройка переключателей компилятора GCC в Qt, QtCreator и QMake

    Масштаб (или центр) водяного знака с ffmpeg до того же разрешения, что и выходной файл

    Использование двух classов CSS для одного элемента

    Как использовать обработчик Android для обновления TextView в streamе пользовательского интерфейса?

    Изменение библиотеки OpenSSL в приложении Android для HttpClient

    SWT – OS не доступен для monoширинного шрифта

    Счет живого персонажа для EditText

    stringbuilder против строки concat

    Давайте будем гением компьютера.