By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,978 Members | 1,771 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,978 IT Pros & Developers. It's quick & easy.

Custom ASSERT macro

P: n/a
I know the preprocessor is evil, but I'd like to know what's going on in the
following code.

The problem is when the num variable is used in the ASSERT macro inside
main(). When running the code, I get the following error from Visual
C++.NET 2003:

warning C4806: '==' : unsafe operation: no value of type 'bool' promoted to
type 'int' can equal the given constant

#define DEBUG 2

#include <iostream>

using namespace std;

#if DEBUG == 0

#define ASSERT(n)

#elif DEBUG == 1

#define ASSERT(n) if(!n) { cout << #n << " failed" << endl; }

#elif DEBUG == 2

#define ASSERT(n) \

if(!n) { \

cout << #n << " failed on line " << __LINE__ << endl; \

} \

else { \

cout << #n << " passed on line " << __LINE__ << endl; \

}

#endif

int main() {

bool flag = true;

int num = 5;

ASSERT(flag == true);

ASSERT(flag == false);

// when I change the below to ASSERT((num == 5)); it works perfectly.

// what's wrong with the version below?

ASSERT(num == 5);

return 0;

}

Thanks in advance for your help.
Jul 22 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Stephen Tyndall wrote:
I know the preprocessor is evil, but I'd like to know what's going on in the
following code.

The problem is when the num variable is used in the ASSERT macro inside
main(). When running the code, I get the following error from Visual
C++.NET 2003:

warning C4806: '==' : unsafe operation: no value of type 'bool' promoted to
type 'int' can equal the given constant

#define DEBUG 2

#include <iostream>

using namespace std;

#if DEBUG == 0

#define ASSERT(n)

#elif DEBUG == 1

#define ASSERT(n) if(!n) { cout << #n << " failed" << endl; }

#elif DEBUG == 2

#define ASSERT(n) \

if(!n) { \

cout << #n << " failed on line " << __LINE__ << endl; \

} \

else { \

cout << #n << " passed on line " << __LINE__ << endl; \

}

#endif

int main() {

bool flag = true;

int num = 5;

ASSERT(flag == true);

ASSERT(flag == false);

// when I change the below to ASSERT((num == 5)); it works perfectly.

// what's wrong with the version below?

ASSERT(num == 5);
Think about it. What does the line above expand to?
return 0;

}


HTH,
--ag

--
Artie Gold -- Austin, Texas

"What they accuse you of -- is what they have planned."
Jul 22 '05 #2

P: n/a
* Stephen Tyndall:
I know the preprocessor is evil, but I'd like to know what's going on in the
following code.

The problem is when the num variable is used in the ASSERT macro inside
main(). When running the code, I get the following error from Visual
C++.NET 2003:

warning C4806: '==' : unsafe operation: no value of type 'bool' promoted to
type 'int' can equal the given constant

#define DEBUG 2

#include <iostream>

using namespace std;

#if DEBUG == 0

#define ASSERT(n)

#elif DEBUG == 1

#define ASSERT(n) if(!n) { cout << #n << " failed" << endl; }

#elif DEBUG == 2

#define ASSERT(n) \

if(!n) { \

cout << #n << " failed on line " << __LINE__ << endl; \

} \

else { \

cout << #n << " passed on line " << __LINE__ << endl; \

}

#endif

int main() {

bool flag = true;

int num = 5;

ASSERT(flag == true);

ASSERT(flag == false);

// when I change the below to ASSERT((num == 5)); it works perfectly.

// what's wrong with the version below?

ASSERT(num == 5);

return 0;

}


Check out operator precedence. How is the following parsed?

cout << flag == true << " failed." << endl;

I'm surprised it even compiles, but it's late and I don't want
to think about why it could compile right now...

Hth.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #3

P: n/a
* Alf P. Steinbach:
* Stephen Tyndall:
I know the preprocessor is evil, but I'd like to know what's going on in the
following code.

The problem is when the num variable is used in the ASSERT macro inside
main(). When running the code, I get the following error from Visual
C++.NET 2003:

warning C4806: '==' : unsafe operation: no value of type 'bool' promoted to
type 'int' can equal the given constant

#define DEBUG 2

#include <iostream>

using namespace std;

#if DEBUG == 0

#define ASSERT(n)

#elif DEBUG == 1

#define ASSERT(n) if(!n) { cout << #n << " failed" << endl; }

#elif DEBUG == 2

#define ASSERT(n) \

if(!n) { \

cout << #n << " failed on line " << __LINE__ << endl; \

} \

else { \

cout << #n << " passed on line " << __LINE__ << endl; \

}

#endif

int main() {

bool flag = true;

int num = 5;

ASSERT(flag == true);

ASSERT(flag == false);

// when I change the below to ASSERT((num == 5)); it works perfectly.

// what's wrong with the version below?

ASSERT(num == 5);

return 0;

}


Check out operator precedence. How is the following parsed?

cout << flag == true << " failed." << endl;

I'm surprised it even compiles, but it's late and I don't want
to think about why it could compile right now...


Yes it's late, it's late late late, and me Very Sleepy (TM).

Of course it's not expanded like that; you have # in there.

It's the 'if' condition expansion of the last assert that's
the problem, as Artie Gold pointed out.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #4

P: n/a
"Artie Gold" <ar*******@austin.rr.com> wrote in message
news:2l************@uni-berlin.de...
Stephen Tyndall wrote:
I know the preprocessor is evil, but I'd like to know what's going on in the following code.

The problem is when the num variable is used in the ASSERT macro inside
main(). When running the code, I get the following error from Visual
C++.NET 2003:

warning C4806: '==' : unsafe operation: no value of type 'bool' promoted to type 'int' can equal the given constant

#define DEBUG 2

#include <iostream>

using namespace std;

#if DEBUG == 0

#define ASSERT(n)

#elif DEBUG == 1

#define ASSERT(n) if(!n) { cout << #n << " failed" << endl; }

#elif DEBUG == 2

#define ASSERT(n) \

if(!n) { \

cout << #n << " failed on line " << __LINE__ << endl; \

} \

else { \

cout << #n << " passed on line " << __LINE__ << endl; \

}

#endif

int main() {

bool flag = true;

int num = 5;

ASSERT(flag == true);

ASSERT(flag == false);

// when I change the below to ASSERT((num == 5)); it works perfectly.

// what's wrong with the version below?

ASSERT(num == 5);


Think about it. What does the line above expand to?


Oh. I should have realized that, especially with the parentheses thing;
sorry, I'm new at this. Thanks for the help, and the quick response.

return 0;

}

Jul 22 '05 #5

P: n/a
"Stephen Tyndall" <sw*******@hotmail.com> wrote in message
news:Os********************@comcast.com...
#define ASSERT(n) if(!n) { cout << #n << " failed" << endl; }


Besides the missing parentheses, this definition of ASSERT has another
serious problems.
When defining statement macros, you should always think of constructs such
as:
Consider:
if( b )
ASSERT( a );
else
{ /* do stuff */ }
Here the extra ';' after the { } of the expanded macro will prevent 'else'
from being interpreted correctly.
A common solution to this issue is to enclose the contents of the macro in a
do...while(false) block:
#define ASSERT(n) do{ if(!n) { cout << #n << " failed" << endl; } }
while(false)

hth
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 22 '05 #6

P: n/a
> #define ASSERT(n) do{ if(!n) { cout << #n << " failed" << endl; } }
Of course this should be (without the copy-pasted error):
#define ASSERT(n) do{ if(!(n)) { cout << #n << " failed" << endl; } }
Actually, to avoid requiring client code to include <iostream>
(and maybe also to reduce code bloat and possibly improve performance),
I usually prefer to implement ASSERT as something like:

extern void assert_notify_failure(const char* str); // may also take
__FILE__ & __LINE__
#define ASSERT(n) if(n){}else assert_notify_failure(#n)
//here the if+else trick is an alternative to do..while(false)

//then in some implementation file:
#include <iostream>
void assert_notify_failure(const char* str)
{
std::cerr << str << " failed" << std::endl;
}
That's it this time ;)
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Jul 22 '05 #7

P: n/a
"Ivan Vecerina" <NO**********************************@vecerina.com > wrote in
message news:cd**********@newshispeed.ch...
#define ASSERT(n) do{ if(!n) { cout << #n << " failed" << endl; } }

Of course this should be (without the copy-pasted error):
#define ASSERT(n) do{ if(!(n)) { cout << #n << " failed" << endl; } }
Actually, to avoid requiring client code to include <iostream>
(and maybe also to reduce code bloat and possibly improve performance),
I usually prefer to implement ASSERT as something like:

extern void assert_notify_failure(const char* str); // may also take
__FILE__ & __LINE__
#define ASSERT(n) if(n){}else assert_notify_failure(#n)
//here the if+else trick is an alternative to do..while(false)

//then in some implementation file:
#include <iostream>
void assert_notify_failure(const char* str)
{
std::cerr << str << " failed" << std::endl;
}


I was pretty sure the macro I posted wasn't that good; it's from a book I'm
learning from. I don't know a lot about that kind of thing yet but it felt
kind of sloppy somehow.

Thanks for the reply. I'll cut and paste your version of ASSERT for later
use.
Jul 22 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.