简体   繁体   English

C++宏解包加入

[英]C++ macro unpack and join

I am trying to define a C++ struct with variable members by a macro as part of an introspection metadata system.我正在尝试通过宏定义具有变量成员的 C++ 结构作为自省元数据系统的一部分。 Given that I am creating a struct definition I cannot use compile-time templates (right?).鉴于我正在创建一个结构定义,我不能使用编译时模板(对吗?)。 Instead I create a variadic macro that should accept tuples of (type, name) but I have had problems in writing a macro that would expand and join the tuple with a symbol to achieve something like相反,我创建了一个可变参数宏,它应该接受 (type, name) 的元组,但是我在编写一个宏时遇到了问题,该宏将扩展并用符号连接元组以实现类似

JOIN(.,(a,A)) -> aA or JOIN(&,(b,B)) -> b&B . JOIN(.,(a,A)) -> aAJOIN(&,(b,B)) -> b&B

I am working in Visual Studio 2017 and part of my confusion may be the inconsistency in the VA_ARGS expansion in MSVC and GCC: MSVC++ variadic macro expansion我在 Visual Studio 2017 中工作,我的部分困惑可能是 MSVC 和 GCC 中的VA_ARGS扩展不一致: MSVC++ 可变参数宏扩展

My approach has been to write an unpacking macro that simply strips the parenthesis from the tuple and a join macro that would join the arguments by the desired string:我的方法是编写一个解包宏,它简单地从元组中去除括号和一个连接宏,它将通过所需的字符串连接 arguments:

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

But this does not work as it seems the macro is not evaluated in the right order.但这不起作用,因为似乎没有以正确的顺序评估宏。 I have then tried to explicitly expand the arguments, eg #define EXPAND(args) args , but to no luck.然后,我尝试显式扩展 arguments,例如#define EXPAND(args) args ,但没有成功。

I have finally found a workaround by embedding the argument parenthesis in the unpacking, thereby 'forcing' an order of evaluation:我终于通过在解包中嵌入参数括号找到了一种解决方法,从而“强制”评估顺序:

#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))

which works, but seems extremely hacky...这有效,但似乎非常hacky......

My questions are我的问题是

  1. Is there a proper way to achieve the evaluation of the unpacked result?是否有适当的方法来实现对解包结果的评估?
  2. Why do I need the EXPAND?为什么我需要 EXPAND? Without it the expression JOINTUPLE(:,(a,B)) resolves to JOIN (a, B, :) but why is this not further processed to a: B ?没有它,表达式JOINTUPLE(:,(a,B))解析为JOIN (a, B, :)但为什么不进一步处理为a: B
  3. Could there be a way to solve it with token-pasting operator?有没有办法用令牌粘贴运算符来解决它? S would only exist in 3 variants. S仅存在于 3 个变体中。

Following the comment by Quentin , a solution is to include the argument parenthesis in the EXPAND macro:根据Quentin 的评论,解决方案是在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)))

The full solution with variadic arguments follows:使用可变参数 arguments 的完整解决方案如下:

#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__))

which enables the following syntax:这启用了以下语法:

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

An answer to why it is needed to manipulate the syntax with this EXPAND , if it is compiler specific/portable and weather it is good/bad practice would be appreciated.为什么需要使用此EXPAND来操作语法的答案,如果它是特定于编译器的/可移植的并且天气好/坏的做法,将不胜感激。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM