有没有实用的解决方案来删除枚举开关?

问题描述 投票:0回答:1

这个问题的标题听起来有点奇怪,但我想不出更好的措辞。我的问题是这样的;我在一个名为

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
语句,同时保持其使用完整?这对我来说似乎多余,但我不知道什么可以解决这个问题。

我尝试过使用宏来简单地组合标记(

##
),这显然不起作用,因为参数仅在运行时才知道。不过,我在这里不知所措。这个问题有没有解决方案,或者这是最好的解决方案吗?

c switch-statement unions
1个回答
0
投票

您可以使用类似于 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)
© www.soinside.com 2019 - 2024. All rights reserved.