【发布时间】:2022-01-22 00:52:02
【问题描述】:
我想使用 C++ 预处理器为几个不同的值生成几段代码。我将所有这些值输入到表生成宏中。然而,代码的某些部分只需要为值的某些(分离的)子集生成。因此,我想有一个小的表生成宏,然后将它们合并成一个大的(对于必须为所有这些生成的代码)。到目前为止,这部分工作完美无缺。
但是,我需要在代码的某些部分使用逗号作为分隔符(正是为了生成枚举)。不幸的是,这个逗号被替换得太早了(即在宏的函数调用被替换之前)。这里有一个例子可以说明我的问题:
#include <iostream>
#define A(F, SEP) F(one) SEP F(two)
#define B(F, SEP) F(three) SEP F(four)
#define C(F, SEP) A(F, SEP) SEP B(F, SEP)
#define SOME_F(x) x
#define SOME_SEP ,
enum {C(SOME_F, SOME_SEP)} ENUM;
int main()
{
#define ANOTHER_F(x) std::cout << #x << std::endl;
#define ANOTHER_SEP
A(ANOTHER_F, ANOTHER_SEP)
return 0;
}
在这里我想生成一个包含所有值的枚举(它在示例中未使用,但在我的实际代码中我需要它)并打印子集 A 的所有值。如果我尝试编译此示例,它会失败并出现错误error: macro "A" passed 3 arguments, but takes just 2(B 的消息相同)。其原因似乎是,SOME_SEP 宏在 A 被替换之前被替换(并尝试使用 A(F, ,))。
对此的一个相当简单(但丑陋)的解决方法是将 SEP 参数替换为类似函数而不是类似对象的宏(尽管必须为每个调用添加括号)。但是,我想使用类似对象的宏来解决这个问题。在我的网络搜索过程中,我发现很多人有类似的问题,但他们想传递一个模板类型(因此可以通过使用大括号来解决问题(这不适用于逗号作为分隔符)。
【问题讨论】:
-
答案是:你什么都不做。现代 C++ 对宏的要求很少;如果有的话,它们很简短,而且范围非常有限。宏的广泛使用通常会导致错误、难以诊断和难以理解的代码,这些代码通常看起来甚至不像 C++,而是其他一些奇怪的语言。宏只在一堆无用的编码难题网站上流行,它们鼓励不良的编程实践,实际上对它们没有任何其他内在价值。
-
我不明白 - 这里的最终目标是什么?为什么你表现得像一个枚举应该是一个数组?如果要将函数应用于多个项目,请声明一个数组,然后使用该数组。总的来说,这种用法只是令人困惑,我相信你会以不可维护的代码结束。这似乎是 XY 问题——你打算如何使用这样的代码?它解决了什么问题?
标签: c++ macros c-preprocessor preprocessor