Учитывая, что структура должна генерироваться по-разному во время компиляции, учитывая некоторые условия, вы столкнетесь с проблемой того, что весь код, использующий структуру, необходимо будет соответствующим образом изменить.Переключатели компилятора (#ifdef FOO .... #endif
) имеют тенденцию плохо масштабироваться с повышенной сложностью.Если имеется большое количество членов структуры, все необходимые переключатели компилятора создадут из программы ужасный, не поддерживаемый беспорядок.
Существует хорошо известный шаблон проектирования, известный как «X-макросы», который можетиспользоваться для централизации обслуживания в программах в одном месте, а также позволяет выполнять итерации во время компиляции всех элементов.Они также затрудняют чтение кода, и поэтому они являются последним средством.Но они являются стандартом де-факто, и их уродство не масштабируется со сложностью, поэтому они предпочитаются некоторому безумию переключателя компилятора.Это выглядит так:
#define INSTANCE_LIST \
/* name, type */ \
X(name, bool) \
X(val1, bool) \
X(val2, bool) \
typedef struct
{
#define X(name, type) type name;
INSTANCE_LIST
#undef X
} instance_t;
Этот код предварительно обрабатывается в:
typedef struct
{
bool name;
bool val1;
bool val2;
} instance_t;
Единственная часть, которую необходимо сохранить, это "INSTANCE_LIST".Закомментировав строку в списке, этот член структуры исчезнет.Это означает, что весь код, использующий структуру, должен соответственно использовать один и тот же список.Например, давайте добавим код в тот же пример, который перечисляет значения инициализации каждого члена и затем устанавливает их:
#include <stdbool.h>
#include <stdio.h>
#define INSTANCE_LIST \
/* name, type, init */ \
X(name, bool, true) \
X(val1, bool, false) \
X(val2, bool, false) \
typedef struct
{
#define X(name, type, init) type name;
INSTANCE_LIST
#undef X
} instance_t;
int main (void)
{
instance_t inst;
#define X(name, type, init) inst.name = init;
INSTANCE_LIST
#undef X
printf("%d ", inst.name);
printf("%d ", inst.val1);
printf("%d ", inst.val2);
}
Очень гибкий и поддерживаемый - вы можете легко добавить больше элементов структуры без изменения любого другого макросачем список.Но, как уже упоминалось, недостатком является то, что код выглядит довольно загадочно, особенно для тех, кто не привык к этому шаблону проектирования.