如何在宏后要求分号

How to require a semicolon after a macro

所以我正在编写一个库,必须使用 -pedantic -ansi -std=c++98 -Werror-Weverything 为 clang 和 -Wall -Wextra 为 gcc 构建,我有这个宏 TESTSUITE(X)像这样在全球范围内使用:

TESTSUITE(current testsuite);

它所做的是使用以下字符串调用函数(在程序启动时通过初始化虚拟变量):

#define TESTSUITE(name) \
static int ANONYMOUS_VARIABLE(SOME_PREFIX) = setTestSuiteName(#name)

问题是这会在 -Wglobal-constructors.

的 clang 下生成警告

如果我像这样用 _Pragma 包围它:

#define TESTSUITE(name)                                              \
_Pragma("clang diagnostic push");                                    \
_Pragma("clang diagnostic ignored \"-Wglobal-constructors\"");       \
static int ANONYMOUS_VARIABLE(SOME_PREFIX) = setTestSuiteName(#name) \
_Pragma("clang diagnostic pop")

编译时不需要使用宏后的分号(缺少时-pedantic会报错)。

如果我在宏的末尾添加这个

static int ANONYMOUS_VARIABLE(SOME_PREFIX) = 5

分号将是必需的,但我会收到一个未使用变量的警告,我无法将其静音(因为如果我用 _Pragma 语句包围它,我将返回到不需要分号的方块 1)。

那么有没有人知道我如何要求分号并且还有 0 个警告?

您可以在宏的末尾添加一个函数声明:

#define TESTSUITE(name)  \
//...                    \
void ANONYMOUS_FUNCTION()

Demo

函数名称甚至不必在不同的 TESTSUITE 宏中有所不同。如果它只是不在其他任何地方使用就足够了,所以它不参与任何重载。

我在宏的末尾使用 enum {} 来强制使用分号。

这在内部和外部都有效 类 和功能。

这种方法不会污染任何命名空间,也不会生成任何代码。

类似于@thomas-eding 的解决方案,您可以将 static_assert(true, "") 放在宏的末尾以要求分号。

这在内部和外部都有效 类 和功能。

并且不污染任何命名空间,不生成任何代码。

聚会有点晚了,但我想我会为稍后寻找答案的人插话。实现此目的的推荐方法是将宏包装在 do {....} while (0) 中。这只会执行一次,编译器通常会为您优化它,不会生成额外的代码,但仍会实现抽象。

来源:https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html