如何在宏之后需要分号

时间:2016-02-21 00:33:07

标签: c++ c-preprocessor compiler-warnings suppress-warnings

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

TESTSUITE(current testsuite);

它的作用是使用字符串调用函数(在程序启动时通过初始化虚拟var):

#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个警告?

4 个答案:

答案 0 :(得分:4)

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

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

Demo

函数名称甚至不必在不同的TESTSUITE宏之间有所不同。如果它在其他任何地方都没有使用它就足够了,所以它不会参与任何超载。

答案 1 :(得分:3)

聚会晚了一点,但我想我会为以后寻找答案的人而欢呼。推荐的方法是将宏包装在do {....} while (0)中。该操作仅执行一次,编译器通常会为您优化此操作,不生成任何额外的代码,但仍实现抽象。

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

答案 2 :(得分:2)

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

这在类和函数的内部和外部都起作用。

它不污染任何名称空间,也不生成任何代码。

答案 3 :(得分:0)

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

这在类和函数的内部和外部都起作用。

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