【问题标题】:How to join two table generating macros into a large one using the C++ preprocessor using a comma如何使用 C++ 预处理器使用逗号将两个生成表的宏连接成一个大宏
【发布时间】: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


【解决方案1】:

只需使用括号,然后删除它们。

#include <iostream>

#define EXP(...)  __VA_ARGS__

#define A(F, SEP) F(one) EXP SEP F(two)
#define B(F, SEP) F(three) EXP SEP F(four)
#define C(F, SEP) A(F, SEP) EXP SEP B(F, SEP)

#define SOME_F(x) x
enum {C(SOME_F, (,))} ENUM;

int main() {
    #define ANOTHER_F(x) std::cout << #x << std::endl;
    A(ANOTHER_F, ())
}

总的来说,这是一种奇怪的用法,看起来也很奇怪。考虑使用BOOST_PP_SEQ_FOR_EACH 和类似的FOREACH_* 宏。在宏内定义要迭代的元素列表很奇怪——我希望它在外部定义并作为参数传递。喜欢:

#define LIST1  (one)(two)

#define CALLBACK(x)  x
SUPER_FOREACH(LIST1, CALLBACK, (,))

如果您想对枚举进行字符串化,另请参阅 How to convert an enum type variable to a string?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多