Using the assert macro while global variables are initialized

702 views Asked by At

In the following code, the first assert does not compile because, in MSVC2015RC at least, it is defined essentially as assert(expression) (void)(!!(expression)).

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

The error message is

C2062 type 'void' unexpected

The second assert compiles without problems but it is not executed unless foo() is called. I would like to use assert while the global variables are being initialized. Is there are any workaround?

2

There are 2 answers

0
Barry On BEST ANSWER

Two issues here.

First, only declarations (e.g. variable, class, function) can go in global scope. assert() is not a declaration, that's why you can't do there.

That might lead to a workaround to just shove it into a declaration, like:

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

On gcc, the above compiles fine and will assert if x is not 1. However, on clang, this leads to the second problem: assert() really wants to be used in a function - it uses a macro which is only defined in a function.

So for that, you could hack together a class declaration:

#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);

That will create a global variable in a semi-anonymous namespace that in its constructor will assert the expression. This works on both clang and gcc.

0
john zhao On

in c/c++, statement such as

x==1

can't be wrote beyond function

assert( x == 1 );

will be replaced during precompiling

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

it is a statement, can't be wrote beyond function definition