我正在寻找一种定义结构的解决方案,用户可以如示例中那样启用/禁用结构成员(伪代码):
#define DEF_STRUCT_1(NAME,VAL1,VAL2) \
struct my_struct_t \
{ \
#if(NAME == TRUE) \
bool name; \
#endif \
#if(VAL1 == TRUE) \
bool val1; \
#endif \
#if(VAL2 == TRUE) \
bool val2; \
#endif \
} instance1
void main() {
DEF_STRUCT_1(TRUE,FALSE,TRUE);
instance1.name = true;
//instance1.val1 = false; // error, unavailable
instance1.val2 = false;
}
答案 0 :(得分:5)
我不确定这有什么用,但是以下内容可以满足您的要求:
#define CONDITIONAL_TRUE(code) code
#define CONDITIONAL_FALSE(code)
#define DEF_STRUCT_1(NAME,VAL1,VAL2) \
struct my_struct_t \
{ \
CONDITIONAL_##NAME(bool name;) \
CONDITIONAL_##VAL1(bool val1;) \
CONDITIONAL_##VAL2(bool val2;) \
} instance1
int main() {
DEF_STRUCT_1(TRUE,FALSE,TRUE);
instance1.name = true;
//instance1.val1 = false; // error, unavailable
instance1.val2 = false;
}
所有TRUE
/ FALSE
参数必须在编译时可用。而且,如果您希望在同一程序中使用这些参数的多个版本,则还应该使结构名称成为参数。
由于您说这是针对库的,因此尚不清楚您如何计划库代码能够访问此结构,因为它需要知道哪些成员可用。这大大降低了该方法的实用性。
库使用的一种更常见的方法是拥有一个config.h文件,该文件可由库用户编辑,并带有诸如#define USE_NAME_MEMBER 1
之类的定义。然后,您可以使用struct
伪指令创建普通的#if
定义:
//in mylibrary.h:
#include <mylibrary_config.h>
struct my_struct_t {
#if USE_NAME_MEMBER
bool name;
#endif
/...
};
然后,您还将在访问#if
成员的任何库代码周围放置name
指令。
答案 1 :(得分:0)
鉴于给定的条件,在编译时需要以不同的方式生成结构,因此您将面临一个问题,即所有使用该结构的代码都需要进行相应的修改。编译器开关(#ifdef FOO .... #endif
)的伸缩性往往会随着复杂性的增加而恶化。如果有大量的struct成员,则所有需要的编译器开关都将使程序变得更糟,无法维护。
有一个众所周知的设计模式,称为“ 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”。通过注释掉列表中的一行,该结构成员将消失。这意味着所有使用该结构的代码都必须相应地使用相同的列表。例如,让我们在同一示例中添加代码,该代码列出每个成员的init值,然后进行设置:
#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);
}
非常灵活且可维护-您可以轻松添加更多的结构成员,而无需更改列表以外的任何其他宏。但是,如上所述,不利的一面是该代码看起来很神秘,尤其是对于那些不习惯这种设计模式的人。