C++宏解压缩并加入

C++ macro unpack and join

本文关键字:解压缩 C++      更新时间:2023-10-16

我正在尝试通过宏定义一个具有变量成员的C++结构,作为内省元数据系统的一部分。鉴于我正在创建一个结构定义,我无法使用编译时模板(对吗?相反,我创建了一个应该接受(类型,名称(元组的可变参数宏,但是我在编写一个宏时遇到了问题,该宏将扩展并用符号连接元组以实现类似

JOIN(.,(a,A)) -> a.AJOIN(&,(b,B)) -> b&B.

我在Visual Studio 2017中工作,我的部分困惑可能是MSVC和GCC中VA_ARGS扩展的不一致: MSVC++ 可变参数宏展开

我的方法是编写一个解压缩宏,它只是从元组中去除括号,以及一个连接宏,该宏将通过所需的字符串连接参数:

#define UNPACK(a, b) a, b
#define JOINAB(a, b, S) a S b
#define JOINTUPLE(S, ab) JOINAB(UNPACK ab, S)

但这不起作用,因为宏似乎没有以正确的顺序进行评估。然后我试图明确扩展论点,例如#define EXPAND(args) args,但没有运气。

我终于找到了一种解决方法,通过在解包中嵌入参数括号,从而"强制"计算顺序:

#define EXPAND(...) __VA_ARGS__
#define UNPACK(a, b) (a, b
#define JOINAB(a, b, S) a S b
#define JOINTUPLE(S, ab) EXPAND(JOINAB UNPACK ab, S))

这有效,但似乎非常笨拙...

我的问题是

  1. 有没有适当的方法来实现对未包装结果的评估?
  2. 为什么我需要扩展?没有它,表达式JOINTUPLE(:,(a,B))解析为JOIN (a, B, :)但为什么不进一步处理以a : B
  3. 有没有办法用令牌粘贴运算符来解决它?S只存在于 3 个变体中。

在昆汀的评论之后,解决方案是在EXPAND宏中包含参数括号:

#define EXPAND(...) __VA_ARGS__
#define UNPACK(a, b) a, b
#define JOINAB(a, b, S) a S b
#define JOINTUPLE(S, ab) EXPAND(JOINAB EXPAND((UNPACK ab, S)))

具有可变参数的完整解决方案如下:

#define JOIN1(S, aA) JOINTUPLE(S, aA)
#define JOIN2(S, aA, bB) JOINTUPLE(S, aA), JOINTUPLE(S, bB)
#define JOIN3(S, aA, bB, cC) JOINTUPLE(S, aA), JOINTUPLE(S, bB), JOINTUPLE(S, cC)
#define JOINN(_1, _2, _3, N, ...) JOIN##N
#define JOIN(S,...) _EXPAND(JOINN(__VA_ARGS__,3,2,1)(S,__VA_ARGS__))

这将启用以下语法:

JOIN(:, (a, A)) // Expands to "a : A"
JOIN(., (a, A), (b, B)) // Expands to "a . A, b . B"

为什么需要用这个EXPAND操作语法的答案,如果它是编译器特定的/可移植的,并且天气是好/坏的做法,将不胜感激。