Каков наилучший метод для реализации перегрузки функций в C? - PullRequest
1 голос
/ 31 октября 2019

Я сейчас пишу заголовочный файл data_structures.h, который содержит несколько различных структур данных, таких как динамические массивы и деревья. Моя проблема в том, что я хочу иметь функцию типа get_element(), которую можно вызывать как с экземпляром динамического массива, так и с деревом или любой другой структурой данных.

Я знаю, что такой вещи неткак перегрузка функций в C, но есть ли лучшие методы, чтобы обойти эту проблему? Было бы лучше иметь просто другое имя функции для каждой структуры данных, например tree_get_element()?

int get_element(struct dynarray *a, int index);
int get_element(struct tree *t, int index);

Ответы [ 2 ]

3 голосов
/ 31 октября 2019

Было бы лучше иметь другое имя функции для каждой структуры данных, например, tree_get_element()?

Да, именно так обычно это делается в C.

Но если вы используете компилятор C11, вы можете расширить это с помощью общих выражений:

int dynarray_get_element(struct dynarray *a, int index);
int tree_get_element(struct tree *t, int index);

#define get_element(x, index)                   \
    _Generic((x),                               \
        struct dynarray *: dynarray_get_element,\
        struct tree *    : tree_get_element     \
    )((x), (index))
1 голос
/ 31 октября 2019

Существует два основных подхода к решению этой проблемы в C:

(1) Используйте union и каждый тип pointer to user-class [вы можете попробовать разные символы для каждого union member сообщить функции, какой вызов вы сделали];

(2) Используйте void * в качестве pointer to user-class [в этом случае вам необходимо использовать char * или строковый тип для указания имени типа].

Теперь, например, (1) будет закодировано как:

union _dynarrtr_ {
    struct dynarray *a;
    struct tree *t;
};
typedef union _dynarrtr_ UDynArrTree;

/*UATChar is either 'a' or 't' (or whichever other union members there are)*/
int get_element(char UATChar, UDynArrTree *UATPtr, int index);

И, (2) будет закодировано следующим образом:

/*Here, you can test 'typeStr' against the name of each type*/
int get_element(const char *typeStr, void *objPtr, int index);
...