
there were a discussion recentrly about verifying arguments of assertion macros while checks are turned off i've got an idea of how to check the argument(s) and guarantee zero code size and runtime overhead suppose we have a canonical macro 'assert()' while compiling with NDEBUG macro defined it expands to nothing which may cause annoying compiler warnings (like 'var isn't referenced') assert() checks a condition i.e. the argument must be convertible to bool then we can write #define assert(cond) sizeof(cond) but to check if the arg converts to bool we can write something like #define assert(cond) sizeof(bool(cond)) which may or may not expand to some code (i.e. machine instructions) to ensure zero overhead i suggest the following scheme: #ifdef NDEBUG typename<size_t s> struct dummy_for_assert; #define my_assert(cond)\ typedef dummy_for_assert<sizeof(bool(cond))> typedef_dummy_for_assert #elif #define my_assert(cond) assert(cond) #endif i hope you got the idea by the way the typedef may be enclosed in a scope in order not to mess around: #define my_assert(cond)\ do {\ typedef dummy_for_assert<sizeof(bool(cond))> t;\ } while(false) although all this looks like a big kludge i believe more advanced programmers would make it work very well (and even make it idiomatic) if that already has been discussed sorry for wasting your time -- Pavel

AMDG DE wrote:
but to check if the arg converts to bool we can write something like
#define assert(cond) sizeof(bool(cond))
#define assert(cond) sizeof(bool(cond)) int main() { int i = 0; assert(i); } warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
which may or may not expand to some code (i.e. machine instructions)
If this isn't completely optimized away, and you actually care, you should get a better compiler. In Christ, Steven Watanabe

on 12.03.2010 at 20:34 Steven Watanabe wrote :
but to check if the arg converts to bool we can write something like
#define assert(cond) sizeof(bool(cond))
#define assert(cond) sizeof(bool(cond)) int main() { int i = 0; assert(i); }
warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) i guess static_cast will work i.e. #define assert(cond) sizeof(static_cast<bool>(cond))
or something like #define assert(cond) sizeof(cond ? char : int)
which may or may not expand to some code (i.e. machine instructions) If this isn't completely optimized away, and you actually care, you should get a better compiler. is that your own motto or the boost one? my point is: it's not always possible to do that
-- Pavel

AMDG DE wrote:
on 12.03.2010 at 20:34 Steven Watanabe wrote :
If this isn't completely optimized away, and you actually care, you should get a better compiler.
is that your own motto or the boost one? my point is: it's not always possible to do that
In this case, I'm perfectly serious. This is such a trivial compiler optimization, that if it matters and the compiler doesn't do it, you probably have much worse problems. As far as I know, no Boost library worries about micro-optimization at this level. In Christ, Steven Watanabe

On Fri, Mar 12, 2010 at 11:59 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
DE wrote:
on 12.03.2010 at 20:34 Steven Watanabe wrote :
If this isn't completely optimized away, and you actually care, you should get a better compiler.
is that your own motto or the boost one? my point is: it's not always possible to do that
In this case, I'm perfectly serious. This is such a trivial compiler optimization, that if it matters and the compiler doesn't do it, you probably have much worse problems.
+1, this is similar to the recommendation to use if(debug) instead of #ifdef _DEBUG, where debug is defined as something like: static bool const debug=true; //or false You can safely trust your compiler to optimize the if away, or if not you shouldn't care about it (or else you have much bigger problems.) Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

DE wrote:
there were a discussion recentrly about verifying arguments of assertion macros while checks are turned off
I guess this would be closer to what you want: // ------------------------------------------ #include <cassert> #ifdef NDEBUG #ifdef assert #undef assert static bool assert_helper(const bool&) { return true; } #define assert(cond) if (sizeof(assert_helper(cond))) {} #endif #endif // ------------------------------------------ The following compiles without warning, regardless of NDEBUG being defined or not (I used g++ test.cpp -Wall -Wextra -O3): // -------------------- int main() { int i = 0; assert(i); } // -------------------- And the next snippet always fails, regardless of NDEBUG being defined or not, because an instance of A cannot be interpreted as bool. // -------------------- class A {}; int main() { assert(A()); } // --------------------- And finally, the next snippet demonstrates that it is still safely optimized away in case of NDEBUG being defined. // -------------------- #include <iostream> int test() { std::cerr << "NDEBUG is OFF" << std::endl; return 0; } class A {}; int main() { assert(test()); } // --------------------- Regards, Roland

AMDG Roland Bock wrote:
DE wrote:
there were a discussion recentrly about verifying arguments of assertion macros while checks are turned off
I guess this would be closer to what you want:
// ------------------------------------------ #include <cassert> #ifdef NDEBUG #ifdef assert #undef assert static bool assert_helper(const bool&) { return true; } #define assert(cond) if (sizeof(assert_helper(cond))) {} #endif #endif // ------------------------------------------
The following compiles without warning, regardless of NDEBUG being defined or not (I used g++ test.cpp -Wall -Wextra -O3):
// -------------------- int main() { int i = 0; assert(i); } // --------------------
MSVC 9.0 /W4 .\scratch.cpp(14) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) .\scratch.cpp(14) : warning C4127: conditional expression is constant .\scratch.cpp(7) : warning C4505: 'assert_helper' : unreferenced local function has been removed In Christ, Steven Watanabe

Steven Watanabe wrote:
MSVC 9.0 /W4
.\scratch.cpp(14) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) .\scratch.cpp(14) : warning C4127: conditional expression is constant .\scratch.cpp(7) : warning C4505: 'assert_helper' : unreferenced local function has been removed
In Christ, Steven Watanabe
OK, seems I need a sterner compiler. Thanks :-)

Roland Bock wrote:
Steven Watanabe wrote:
MSVC 9.0 /W4
.\scratch.cpp(14) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) .\scratch.cpp(14) : warning C4127: conditional expression is constant .\scratch.cpp(7) : warning C4505: 'assert_helper' : unreferenced local function has been removed
OK, seems I need a sterner compiler.
s/sterner/noisier/? C4800 seems ridiculous. Writing code using int as a Boolean is common to C code. Why would VC 9 inflict useless noise when compiling such code? Besides, if the variable is int, and it is needed in a Boolean context, what else would the developer do? I've seen use of the conditional operator to avoid that warning. I suspect that produces worse code than what is done when "forcing value to bool 'true' or 'false'." C4505 seems useless. Why would one need to know that unused code isn't included in the object code? Either it is used and will cause a link error or it isn't and its absence isn't important. Did I miss a case? _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert wrote:
Roland Bock wrote:
Steven Watanabe wrote:
MSVC 9.0 /W4
.\scratch.cpp(14) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) .\scratch.cpp(14) : warning C4127: conditional expression is constant .\scratch.cpp(7) : warning C4505: 'assert_helper' : unreferenced local function has been removed
OK, seems I need a sterner compiler.
s/sterner/noisier/?
C4800 seems ridiculous. Writing code using int as a Boolean is common to C code. Why would VC 9 inflict useless noise when compiling such code? Besides, if the variable is int, and it is needed in a Boolean context, what else would the developer do? I've seen use of the conditional operator to avoid that warning. I suspect that produces worse code than what is done when "forcing value to bool 'true' or 'false'."
C4505 seems useless. Why would one need to know that unused code isn't included in the object code? Either it is used and will cause a link error or it isn't and its absence isn't important. Did I miss a case?
I agree. Still, I hope that static_cast is allowed to remove C4800 and C4505 does not have a brother which talks about unreferenced classes or their methods. C4127 is a valid warning, of course. I used it to get rid of "statement has no effect" warning. I just read that that kind of warning can be gotten rid of by casting to void (works for g++ 4.2.4). So here is my new attempt (probably the last for this week): #include <cassert> #ifdef NDEBUG #ifdef assert #undef assert class assert_helper { public: static const bool check(const bool&) { return true; } }; #define assert(cond) static_cast<void>(sizeof(assert_helper::check(static_cast<bool>(cond)))); #endif #endif int main() { int i = 0; assert(i); }

AMDG Roland Bock wrote:
Stewart, Robert wrote:
C4800 seems ridiculous. Writing code using int as a Boolean is common to C code. Why would VC 9 inflict useless noise when compiling such code? Besides, if the variable is int, and it is needed in a Boolean context, what else would the developer do? I've seen use of the conditional operator to avoid that warning. I suspect that produces worse code than what is done when "forcing value to bool 'true' or 'false'."
I agree. Still, I hope that static_cast is allowed to remove C4800
Nope. .\scratch.cpp(20) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Roland Bock wrote:
Stewart, Robert wrote:
C4800 seems ridiculous. Writing code using int as a Boolean is common to C code. Why would VC 9 inflict useless noise when compiling such code? Besides, if the variable is int, and it is needed in a Boolean context, what else would the developer do? I've seen use of the conditional operator to avoid that warning. I suspect that produces worse code than what is done when "forcing value to bool 'true' or 'false'."
I agree. Still, I hope that static_cast is allowed to remove C4800
Nope.
.\scratch.cpp(20) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
But the rest of the warnings are gone? In that case, adding a few more versions of check should do the trick, right? I added one for int, now, more would probably be required, I guess. #include <cassert> #ifdef NDEBUG #ifdef assert #undef assert class assert_helper { public: static const bool check(const bool&) { return true; } static const bool check(const int&) { return true; } }; #define assert(cond) static_cast<void>(sizeof(assert_helper::check(cond))); #endif #endif int main() { int i = 0; assert(i); }

Steven Watanabe:
AMDG
Roland Bock wrote:
Stewart, Robert wrote:
C4800 seems ridiculous. Writing code using int as a Boolean is common to C code. Why would VC 9 inflict useless noise when compiling such code? Besides, if the variable is int, and it is needed in a Boolean context, what else would the developer do? I've seen use of the conditional operator to avoid that warning. I suspect that produces worse code than what is done when "forcing value to bool 'true' or 'false'."
I agree. Still, I hope that static_cast is allowed to remove C4800
Nope.
.\scratch.cpp(20) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
C4800 is avoided with expr? true: false. In this case, sizeof( expr? 0: 0 ) will also work, as we don't care about the value.

Peter Dimov wrote:
Steven Watanabe:
AMDG
Roland Bock wrote:
Stewart, Robert wrote:
C4800 seems ridiculous. Writing code using int as a Boolean is common to C code. Why would VC 9 inflict useless noise when compiling such code? Besides, if the variable is int, and it is needed in a Boolean context, what else would the developer do? I've seen use of the conditional operator to avoid that warning. I suspect that produces worse code than what is done when "forcing value to bool 'true' or 'false'."
I agree. Still, I hope that static_cast is allowed to remove C4800
Nope.
.\scratch.cpp(20) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
C4800 is avoided with expr? true: false. In this case, sizeof( expr? 0: 0 ) will also work, as we don't care about the value.
Oh! So the following should do the trick? That would be neat. It certainly works for gcc. #include <cassert> #ifdef NDEBUG #ifdef assert #undef assert #define assert(cond) static_cast<void>(sizeof(cond? 0: 0)); #endif #endif int main() { int i = 0; assert(i); }
participants (6)
-
DE
-
Emil Dotchevski
-
Peter Dimov
-
Roland Bock
-
Steven Watanabe
-
Stewart, Robert