如何使用宏从常数列表创建查找表?

huangapple go评论47阅读模式
英文:

How to create a lookup table from list of constants with a macro?

问题

我想创建一个查找表,将常量值映射到常量名称。

struct char TABLE[128][32] = { [CONST_1] = "CONST_1", [CONST_2] = "CONST_2", ... };

我为此定义了两个宏。

#define TBL(N, S, ...) static char N[S][1 << 5] = { __VA_ARGS__ };
#define V(T) [T] = #T

这样,我可以这样定义我的表格。

TBL(CODES, LastExtensionError,
    V(Success), V(BadRequest), V(BadValue), ...);

是否可以避免将每个常量用 V 包装,而像这样写?

TBL(CODES, LastExtensionError,
    Success, BadRequest, BadValue, ...);
英文:

I want to create a lookup up table from a constant value to a constant name

struct char TABLE[128][32] = { [CONST_1] = &quot;CONST_1&quot;,[CONST_2] = &quot;CONST_2&quot;, ... };

I defined two macros for that

#define TBL(N, S, ...) static char N[S][1 &lt;&lt; 5] = { __VA_ARGS__ };
#define V(T) [T] = #T

So I can define my table like that,

TBL (CODES, LastExtensionError,
	   V (Success), V (BadRequest), V (BadValue), ... );

Is it possible to avoid wrapping each constant with V and write something like?

TBL (CODES, LastExtensionError,
	   Success, BadRequest, BadValue, ...);

答案1

得分: 2

> 是否有可能避免用 V 包装每个常数并写类似这样的代码?

这是C预处理器,无论如何,您必须枚举所有可能的迭代。您可以编写一个foreach宏并将其应用于每个元素。

我看不到在宏后面隐藏一个简单的 static char N[S][1 &lt;&lt; 5] = 的价值。只需写 static char CODES[LastExtensionError][1 &lt;&lt; 5] =。如果您确实想要重复 [1 &lt;&lt; 5],考虑制作一个结构。

#define FOREACH_1(f, _1) f(_1)
#define FOREACH_2(f, _1, ...) f(_1) FOREACH_1(f, VA_ARGS)
#define FOREACH_3(f, _1, ...) f(_1) FOREACH_2(f, VA_ARGS)
#define FOREACH_4(f, _1, ...) f(_1) FOREACH_3(f, VA_ARGS)
#define FOREACH_5(f, _1, ...) f(_1) FOREACH_4(f, VA_ARGS)
/* 等等。根据需要添加更多情况 */
#define FOREACH_N(_5,_4,_3,_2,_1,N,...) FOREACH##N
#define FOREACH(f, ...) FOREACH_N(VA_ARGS,_5,_4,_3,2,_1)(f, VA_ARGS)

#define TBL_FOREACH_CB(a) [a] = #a,
#define TBL_INIT(...) { FOREACH(TBL_FOREACH_CB, VA_ARGS) }

static char CODES[LastExtensionError][1 << 5] = TBL_INIT(
Success,
BadRequest,
BadValue
)

如果您不想自己编写代码,可以使用诸如 BOOST_PP_FORP99_FOR 的库。

此外,这样写成 static char CODES[N][1&lt;&lt;5] 似乎有些奇怪,而不是像 static const char *const CODES[N]。奇怪的是值是可变的,并且所有字符串都有恒定的长度,听起来像是浪费了内存。

英文:

> Is it possible to avoid wrapping each constant with V and write something like?

This is C preprocessor, one way or the other you have to enumerate all possible iterations. You can write a foreach macro and apply it on each element.

I see no value in hiding a simple static char N[S][1 &lt;&lt; 5] = behind a macro. Just write static char CODES[LastExtensionError][1 &lt;&lt; 5] =. If you do want to repeat [1 &lt;&lt; 5], consider making a structure.

#define FOREACH_1(f, _1) f(_1)
#define FOREACH_2(f, _1, ...) f(_1) FOREACH_1(f, __VA_ARGS__)
#define FOREACH_3(f, _1, ...) f(_1) FOREACH_2(f, __VA_ARGS__)
#define FOREACH_4(f, _1, ...) f(_1) FOREACH_3(f, __VA_ARGS__)
#define FOREACH_5(f, _1, ...) f(_1) FOREACH_4(f, __VA_ARGS__)
/* etc. add more cases as many as you need */
#define FOREACH_N(_5,_4,_3,_2,_1,N,...)  FOREACH##N
#define FOREACH(f, ...)  FOREACH_N(__VA_ARGS__,_5,_4,_3,_2_,_1)(f, __VA_ARGS__)

#define TBL_FOREACH_CB(a)  [a] = #a,
#define TBL_INIT(...)  { FOREACH(TBL_FOREACH_CB, __VA_ARGS__) }

static char CODES[LastExtensionError][1 &lt;&lt; 5] = TBL_INIT(
    Success,
    BadRequest,
    BadValue
)

You could use a library like BOOST_PP_FOR or P99_FOR if you do not want to write it yourself.

Also, it sounds odd that this is static char CODES[N][1&lt;&lt;5] and not like static const char *const CODES[N]. It's odd that values are mutable, and all strings have constant length, sounds like wasted memory.

答案2

得分: 1

这是一个随着行数呈指数级增长的解决方案:

#define CM__0(P,f,...) CM_P1(CM_P1(CM_P1(CM_P1(CM_P1(CM_##f(,P##__VA_ARGS__))))))
#define CM__1(P,f,...) CM_P2(CM_P2(CM_P2(CM_P2(CM_P2(CM_##f(,P##__VA_ARGS__))))))
#define CM__2(P,f,...) CM_P3(CM_P3(CM_P3(CM_P3(CM_P3(CM_##f(,P##__VA_ARGS__))))))
#define CM__3(P,f,...) CM_P4(CM_P4(CM_P4(CM_P4(CM_P4(CM_##f(,P##__VA_ARGS__))))))
#define CM__4(P,f,...) CM_##f(,P##__VA_ARGS__)
#define CM_P1(x) CM__1 x
#define CM_P2(x) CM__2 x
#define CM_P3(x) CM__3 x
#define CM_P4(x) CM__4 x
#define CM_SCAN(...) __VA_ARGS__
#define CM_EAT(...)
#define CM_LPAREN (
#define CM(...) CM_SCAN(CM_EAT CM_LPAREN CM__0(__VA_ARGS__))

#define TUPLE_AT_1(a,b,...) b
#define CHECK(...) TUPLE_AT_1(__VA_ARGS__,)

#define TBL_0end_0end ,TBL_END
#define CM_0tbl(P,x,...) CHECK(TBL_0end_##x, TBL_NEXT)(,x,P##__VA_ARGS__)
#define TBL_END(...) )
#define TBL_NEXT(P,x,...) (,0tbl,P##__VA_ARGS__) [x] = #x,

#define TBL(...) CM(,0tbl,__VA_ARGS__,0end)

struct char TABLE[128][32] = {
    TBL(CONST_1, CONST_2, CONST_3)
    // [CONST_3] = &quot;CONST_3&quot;, [CONST_2] = &quot;CONST_2&quot;, [CONST_1] = &quot;CONST_1&quot;,
};

如果您需要进一步的解释或帮助,请随时提出。

英文:

Here is a solution that scales exponentially with the number of lines:

// supports 782 iterations ((5^n + 3)/4)
#define CM__0(P,f,...) CM_P1(CM_P1(CM_P1(CM_P1(CM_P1(CM_##f(,P##__VA_ARGS__))))))
#define CM__1(P,f,...) CM_P2(CM_P2(CM_P2(CM_P2(CM_P2(CM_##f(,P##__VA_ARGS__))))))
#define CM__2(P,f,...) CM_P3(CM_P3(CM_P3(CM_P3(CM_P3(CM_##f(,P##__VA_ARGS__))))))
#define CM__3(P,f,...) CM_P4(CM_P4(CM_P4(CM_P4(CM_P4(CM_##f(,P##__VA_ARGS__))))))
#define CM__4(P,f,...) CM_##f(,P##__VA_ARGS__)
#define CM_P1(x) CM__1 x
#define CM_P2(x) CM__2 x
#define CM_P3(x) CM__3 x
#define CM_P4(x) CM__4 x
#define CM_SCAN(...) __VA_ARGS__
#define CM_EAT(...)
#define CM_LPAREN (
#define CM(...) CM_SCAN(CM_EAT CM_LPAREN CM__0(__VA_ARGS__))

#define TUPLE_AT_1(a,b,...) b
#define CHECK(...) TUPLE_AT_1(__VA_ARGS__,)

#define TBL_0end_0end ,TBL_END
#define CM_0tbl(P,x,...) CHECK(TBL_0end_##x, TBL_NEXT)(,x,P##__VA_ARGS__)
#define TBL_END(...) )
#define TBL_NEXT(P,x,...) (,0tbl,P##__VA_ARGS__) [x] = #x,

#define TBL(...) CM(,0tbl,__VA_ARGS__,0end)

struct char TABLE[128][32] = {
    TBL(CONST_1, CONST_2, CONST_3)
    // [CONST_3] = &quot;CONST_3&quot;, [CONST_2] = &quot;CONST_2&quot;, [CONST_1] = &quot;CONST_1&quot;,
};

huangapple
  • 本文由 发表于 2023年7月5日 01:00:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76614635.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定