在初始化全局变量时使用 assert 宏

Using the assert macro while global variables are initialized

在下面的代码中,第一个 assert 不会编译,因为至少在 MSVC2015RC 中,它基本上定义为 assert(expression) (void)(!!(expression)).

int x = 1;
assert( x == 1 );
void foo()
{
    assert( x == 1 );
}

错误信息是

C2062 type 'void' unexpected

第二个断言编译没有问题,但它不会执行,除非调用 foo()。我想在初始化全局变量时使用 assert 。有什么解决方法吗?

这里有两个问题。

首先,只有声明(例如变量、class、函数)可以进入全局范围。 assert() 不是声明,这就是为什么你不能在那里做。

这可能会导致一种变通方法,将其推入声明中,例如:

int x = 1;
namespace assert_x_is_1 {
    bool _ = (assert(x == 1), true);
}

在 gcc 上,上面的代码编译得很好,如果 x 不是 1,就会断言。但是,在 clang 上,这会导致第二个问题:assert() 真的想在函数中使用- 它使用仅在函数中定义的宏。

因此,您可以拼凑一个 class 声明:

#define ASSERT_CLASS2(expr, ctr) namespace assert##ctr { struct Asserter { Asserter() { assert(expr); } } s; }
#define ASSERT_CLASS(expr) ASSERT_CLASS2(expr, __COUNTER__)

int x = 1;
ASSERT_CLASS(x == 1);

这将在半匿名命名空间中创建一个全局变量,该变量将在其构造函数中声明表达式。这适用于 clang 和 gcc。

在c/c++中,语句如

x==1

不能写超出功能

assert( x == 1 );

预编译时会被替换

(void)(!!(x==1));

是语句,不能写在函数定义之外