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

时间:2015-06-18 11:45:10

标签: c++ c++11 assert assertion

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

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

错误消息是

  

C2062 type' void'意想不到

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

2 个答案:

答案 0 :(得分:4)

这里有两个问题。

首先,只有声明(例如变量,类,函数)才能进入全局范围。 assert()不是声明,这就是你无法做到的原因。

这可能导致一种解决方法,只需将其推入声明中,例如:

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

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

因此,你可以将一个类声明破解为一起:

#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。

答案 1 :(得分:0)

在c / c ++中,语句如

x==1

无法在函数

之外编写
assert( x == 1 );

将在预编译期间被替换

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

这是一个声明,不能写在函数定义之外