在下面的代码中,第一个assert
没有编译,因为至少在MSVC2015RC中,它基本上被定义为assert(expression) (void)(!!(expression))
。
int x = 1;
assert( x == 1 );
void foo()
{
assert( x == 1 );
}
错误消息是
C2062 type' void'意想不到
第二个断言编译没有问题,但除非调用foo()
,否则不会执行。我想在初始化全局变量时使用assert
。有没有解决办法?
答案 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)
x==1
无法在函数
之外编写assert( x == 1 );
将在预编译期间被替换
(void)(!!(x==1));
这是一个声明,不能写在函数定义之外