【发布时间】:2020-04-14 08:07:21
【问题描述】:
在我正在处理的一个项目中,有一个记录表达式的宏。我的任务是添加向其中传递多个值并让每个打印件单独打印的功能。
通过 1 到 5 个参数,我设法让这项工作相对容易。它甚至可以很好地传递给一个函数。
我现在遇到的问题是初始化列表不再起作用。该项目使用可变参数来允许在其内部进行数组初始化,例如func(std::vector<int>{0, 1, 0, 1})。由于我已经实现了多 arg 的东西,因此由于逗号而不再起作用。
我知道我可以做func((std::vector<int>{0, 1, 0, 1})),这会很好,但我知道这不会被喜欢作为一种解决方法。有没有办法让这些在没有额外括号的情况下工作,或者在需要时添加额外的括号?
这里有一些相关的 sn-ps:
// Intermediate macro "chooser"
#define func_x(x, A, B, C, D, E, Func, ...) Func
// Macro to be called and used by user
// First param must be blank to allow for 0 argument function
#define func(...) func_x(, ##__VA_ARGS__, \
func_5(__VA_ARGS__), func_4(__VA_ARGS__), func_3(__VA_ARGS__), \
func_2(__VA_ARGS__), func_1(__VA_ARGS__), func_0())
// Macros for 1 through 5 args, calls the func_VA macro.
#define func_1(A1) func_VA(A1)
#define func_2(A1, A2) func_1(A1), func_VA(A2)
#define func_3(A1, A2, A3) func_2(A1, A2), func_VA(A3)
#define func_4(A1, A2, A3, A4) func_3(A1, A2, A3), func_VA(A4)
#define func_5(A1, A2, A3, A4, A5) func_4(A1, A2, A3, A4), func_VA(A5)
// Prints expression and type
// We use a variadic macro to support commas inside expressions (e.g.
// initializer lists):
#define func_VA(...) \
func_macro::DebugOutput(__FILE__, __LINE__, __func__, #__VA_ARGS__) \
.print(func_macro::type_name<decltype(__VA_ARGS__)>(), (__VA_ARGS__))
func(std::vector<int>{0, 1, 0, 1});
// Errors
func((std::vector<int>{0, 1, 0, 1}));
// Works, but also prints the () when logging so not ideal. Better than nothing though.
我一直在尝试在宏的某些部分周围插入括号以尝试修复此问题,但无济于事。喜欢#define func_1(A1) func_VA((A1)) 或类似的。
编辑:我已经取得了一些进展
如果我像你想象的那样调用func_1(std::vector<int>{0, 1, 0, 1});,现在可以像#define func_1(...) func_VA(__VA_ARGS__) 一样声明func_1。
我制作了一个“包装器”宏,它返回(__VA_ARGS__),这允许宏与列表初始化一起正常工作,尽管字符串版本确实有额外的括号。虽然我不能让它以这样的方式工作,这样你(作为用户)就不必在你的数组上调用包装器(这比把括号放在你自己的位置上更难)。
【问题讨论】:
-
为什么要在参数数量上重载宏?只是
#define func(...) func_macro::DebugOutput(__FILE__, ......)? -
@KamilCuk 我不完全确定这是否适用于 DebugOutput 类的工作方式。但也许我遗漏了什么,你能进一步启发我吗?
-
#define func(...) func_macro::DebugOutput(__FILE__, __LINE__, __func__, ##__VA_ARGS__).print(func_macro::type_name<decltype(__VA_ARGS__)>(), (__VA_ARGS__))我完全不知道 DebugOutput 是如何工作的,不是它是如何工作的,你没有展示它。 -
@KamilCuk 是的,IK。它使用 VA 在内部启用逗号以进行初始化,如上面
func_VA评论中所述,老实说,我并不完全确定它是如何做到这一点的。纵观历史,除了使用...而不是普通的变量之外,没有其他细节。 -
It uses VA- 在这种情况下“VA”是什么?你想在dbg(std::vector<int>{0, 1, 0, 1}, std::vector<int>{0, 1, 0, 1});这样的事情上发生什么?
标签: c++ preprocessor