这个问题的标题听起来有点奇怪,但我想不出更好的措辞。我的问题是这样的;我在一个名为
AmbiguousType
的项目中有一个类型,它是这种格式的联合。
Declarations.h
(实用程序头文件)
typedef union AmbiguousType
{
u32 unsigned32;
u64 unsigned64;
i32 signed32;
i64 signed64;
} AmbiguousType;
现在,我有很多辅助函数来更好地方便使用这种类型。我正在研究这些功能,试图找出任何方法来提高它们的效率/减少体积,并意识到一些事情; 大多数函数都有一个
switch
语句作为其主体。 以这个函数为例,它用于分配给给定的模糊类型。
Declarations.c
(实用程序源文件)
/**
* @brief Assign a value to an ambiguous type.
* @param affected The affected variable.
* @param member What state are we making the ambiguous type?
* @param value The value that state will have.
*/
void AssignAmbiguousType(AmbiguousType* affected, AmbiguousTypeSpecifier member,
void* value)
{
switch (member)
{
// Note that "VPTT" is a helper macro to turn a void pointer into the given type.
// U__ - unsigned __ bit integer.
// I__ - signed __ bit integer.
case unsigned32: affected->unsigned32 = VPTT(u32, value); return;
case unsigned64: affected->unsigned64 = VPTT(u64, value); return;
case signed32: affected->signed32 = VPTT(i32, value); return;
case signed64: affected->signed64 = VPTT(i64, value); return;
}
}
我的问题是,是否有一种实用的方法可以从函数中删除这个
switch
语句,同时保持其使用完整?这对我来说似乎多余,但我不知道什么可以解决这个问题。
我尝试过使用宏来简单地组合标记(
##
),这显然不起作用,因为参数仅在运行时才知道。不过,我在这里不知所措。这个问题有没有解决方案,或者这是最好的解决方案吗?
您可以使用类似于 X 宏的宏来减少重复性。这是一个例子。
// define once, include everywhere
#define GEN_SWITCH(DISCRIMINANT, BODY) \
switch(DISCRIMINANT) { \
case DISC(u,32) : BODY(u,32) break; \
case DISC(i,32) : BODY(i,32) break; \
case DISC(u,64) : BODY(u,64) break; \
case DISC(i,64) : BODY(i,64) break; \
default: cannot_happen(); }
#define CONCAT(a,b) a ## b
#define CONCAT2(a,b) CONCAT(a,b)
#define TYPENAME_i(sz) CONCAT2(signed,sz)
#define TYPENAME_u(sz) CONCAT2(unsigned,sz)
#define VPNAME(ui,sz) CONCAT(ui,sz)
#define FIELD(ui,sz) CONCAT2(TYPENAME_,ui)(sz)
#define DISC(ui,sz) CONCAT2(TYPENAME_,ui)(sz)
// more macros that map signedness+size to something
// When you need to generate a switch
#define BODY(ui,sz) affected->FIELD(ui,sz) = VPTT(VPNAME(ui,sz), value);
GEN_SWITCH(member, BODY)
最后一行扩展为以下内容(为了便于阅读而格式化):
switch(member) {
case unsigned32 : affected->unsigned32 = VPTT(u32, value); break;
case signed32 : affected->signed32 = VPTT(i32, value); break;
case unsigned64 : affected->unsigned64 = VPTT(u64, value); break;
case signed64 : affected->signed64 = VPTT(i64, value); break;
default: cannot_happen();
}
这样每个辅助函数都会像这样
#define BODY ... something ...
GEN_SWITCH(discriminant, BODY)