C - Перегрузка метода различными аргументами типа структуры с использованием макроса - PullRequest
1 голос
/ 14 апреля 2020

Я пытаюсь добиться перегрузки метода в C, предпочтительно используя макросы, чтобы заголовок / библиотека могли обрабатывать определения и объявления вместо того, чтобы помещать это на пользователя. Сейчас я прочитал ответ об использовании _Generic, но проблема в том, что мои функции имеют struct типы. Так что нет никакого способа оценить их тип, используя __typeof__ из _Generic. Интересно, есть ли вообще какой-либо способ.

Вот так выглядит мой заголовочный файл (это все, что нас должно интересовать) -

#pragma once

// Macros for generic like use of the data structure

// Macros for the stack type itself
/*
 * Define stack with corresponding type
 * Converts Stack(int) to intstack_t
*/
#define Stack(type) type stack_t

// Macros for functions
/*
 * Define createStack function
 * Converts createStack(int, 5) to create_intstack(5)
*/
#define createStack(type, capacity) create_ ##type ##stack(capacity)

/*
 * Define destroyStack function
 * Converts destroyStack(someIntStack) to destroy_intstack(someIntStack)
 * Where someIntStack is a pointer to a variable of type intstack_t
*/
#define destroyStack(stack) _Generic(stack, intstack_t*: destroy_intstack, charstack_t*: destroy_charstack)(stack)

/*
 * Define push function
 * Converts push(someIntStack, data) to intstack_push(someIntStack, data)
 * Where someIntStack is a pointer to a variable of type intstack_t
*/
#define push(stack, data) _Generic(stack, intstack_t*: intstack_push, charstack_t*: charstack_push)(stack, data)

// Stack structure definition(s)

// int stack definition
typedef struct IntegerStack {
    int top;
    unsigned capacity;
    int* arr;
}intstack_t;

// char stack definition
typedef struct CharacterStack {
    int top;
    unsigned capacity;
    char* arr;
}charstack_t;

//Stack functions

// int stack functions
intstack_t* create_intstack(int);
void destroy_intstack(intstack_t*);
void intstack_push(intstack_t*, int);

// char stack functions
charstack_t* create_charstack(int);
void destroy_charstack(charstack_t*);
void charstack_push(charstack_t*, char);

Большинство объявлений функций ( и косвенно, их соответствующие макросы были удалены, поскольку все они по существу функционируют одинаково. Меня интересует только макрос функции push, как указано. Другие макросы действительно показывают, какой тип использования я собираюсь использовать. Очевидно, что макрос, используемый в push с использованием _Generic, не будет работать, поскольку intstack_t или charstack_t не являются примитивными типами.

Цель состоит в том, чтобы пользователь мог использовать push(stack, data), где стек может быть переменной типа intstack_t* или charstack_t*, а оператор push(stack, data) будет преобразован в intstack_push(stack, data) или charstack_push(stack, data) соответственно.

1 Ответ

2 голосов
/ 15 апреля 2020

_Generic будет работать с любым полным типом, кроме массива переменной длины. И хотя вы не можете связать неполные типы со значениями в вызове _Generic, нет проблем с указателями на неполные типы.

Таким образом, ваш макрос push будет работать нормально, даже если он используется в контексте, где instack_t и charstack_t непрозрачны.

Образец по колиру: http://coliru.stacked-crooked.com/a/7d9b181af2429c5e

...