
Whenever I write a BOOST_ASSERT macro, I'm envious of C++0x static_assert because of its ability to supply a clear error message. I'd really like to be able to write a variant of BOOST_ASSERT like this: #include <boost/assert.hpp> int main() { BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert"); return 0; } And then get debug mode output like this: ***** Internal Program Error - Assertion Failed ***** extended_assert_test.cpp(6): error in int main(void): This will assert Adding the code below at the end of <boost/assert.hpp> will do just that. It isn't totally ready for prime time, but it would be nice to find out if others would like something similar added to<boost/assert.hpp>. --Beman // experimental code #ifndef NDEBUG # include <iostream> # include <cstdlib> # include <boost/current_function.hpp> namespace boost { namespace assertion { namespace detail { inline void extended_assert_failed(char const * msg, char const * function, char const * file, long line) { std::cerr << "***** Internal Program Error - Assertion Failed *****\n"; std::cerr << file << '(' << line << "): error in " << function << ": " << msg << std::endl; std::exit(99999); } }}} // boost::assertion::detail # undef BOOST_EXTENDED_ASSERT # define BOOST_EXTENDED_ASSERT(expr, msg) \ ((expr)? ((void)0): ::boost::assertion::detail::extended_assert_failed\ (msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) #else # define BOOST_EXTENDED_ASSERT(expr, msg) #endif

On Mon, Jan 17, 2011 at 11:06 PM, Beman Dawes <bdawes@acm.org> wrote:
namespace boost { namespace assertion { namespace detail { inline void extended_assert_failed(char const * msg, char const * function, char const * file, long line) { std::cerr << "***** Internal Program Error - Assertion Failed *****\n"; std::cerr << file << '(' << line << "): error in " << function << ": " << msg << std::endl; std::exit(99999); } }}} // boost::assertion::detail
This caught my eye. Do you really want to hard-code the exit value to 99999? Or would you rather use std::abort() just like the normal cassert implementation does? -- Dean Michael Berris about.me/deanberris

On Mon, Jan 17, 2011 at 10:15 AM, Dean Michael Berris < mikhailberis@gmail.com> wrote:
On Mon, Jan 17, 2011 at 11:06 PM, Beman Dawes <bdawes@acm.org> wrote:
namespace boost { namespace assertion { namespace detail { inline void extended_assert_failed(char const * msg, char const * function, char const * file, long line) { std::cerr << "***** Internal Program Error - Assertion Failed
*****\n";
std::cerr << file << '(' << line << "): error in " << function << ": " << msg << std::endl; std::exit(99999); } }}} // boost::assertion::detail
This caught my eye. Do you really want to hard-code the exit value to 99999?
No, and particularly not since 99999 would overflow if int is 16 bits. But... Or would you rather use std::abort() just like the normal
cassert implementation does?
On Windows 7 (at least with VC++), abort() pops up one of those "blah.exe has stopped working" dialog boxes. I haven't been able to kill it, in spite of lots of google searches, and it drives me crazy. That said, std::abort() is probably right for many environments. --Beman

On 17/01/11 17:24, Beman Dawes wrote:
On Mon, Jan 17, 2011 at 10:15 AM, Dean Michael Berris< mikhailberis@gmail.com> wrote:
Or would you rather use std::abort() just like the normal cassert implementation does?
On Windows 7 (at least with VC++), abort() pops up one of those "blah.exe has stopped working" dialog boxes. I haven't been able to kill it, in spite of lots of google searches, and it drives me crazy.
That said, std::abort() is probably right for many environments.
This should do the trick: #include <cassert> #include <crtdbg.h> // Visual C++-specific int main() { #ifdef _MSC_VER // Redirect errors and assert() failures to stderr // instead of pop-up debug message window. // NOTE: Comment this 2 lines for debugging with // Visual C++ debugger to catch assertions inside. _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); #endif //_MSC_VER assert(false && "test"); // no pop-up expected } Best regards, -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org Member of ACCU, http://accu.org

On 1:59 PM, Mateusz Loskot wrote:
On 17/01/11 17:24, Beman Dawes wrote:
On Mon, Jan 17, 2011 at 10:15 AM, Dean Michael Berris< mikhailberis@gmail.com> wrote:
Or would you rather use std::abort() just like the normal cassert implementation does?
On Windows 7 (at least with VC++), abort() pops up one of those "blah.exe has stopped working" dialog boxes. I haven't been able to kill it, in spite of lots of google searches, and it drives me crazy.
That said, std::abort() is probably right for many environments.
This should do the trick:
#include <cassert> #include <crtdbg.h> // Visual C++-specific int main() { #ifdef _MSC_VER // Redirect errors and assert() failures to stderr // instead of pop-up debug message window. // NOTE: Comment this 2 lines for debugging with // Visual C++ debugger to catch assertions inside. _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); #endif //_MSC_VER
assert(false && "test"); // no pop-up expected }
That's if you're in control of the code. Otherwise, \HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\ForceQueue 1 I spent a few google iterations on that one, too. Other parameters have appealing-sounding names <http://msdn.microsoft.com/en-us/library/bb513638%28VS.85%29.aspx>, but don't seem to affect the pop-up.

On Windows 7 (at least with VC++), abort() pops up one of those "blah.exe has stopped working" dialog boxes. I haven't been able to kill it, in spite of lots of google searches, and it drives me crazy.
Before VC++ 10 the default behavior for abort was to print a message (like "foo.exe has requested the runtime to terminate in an usual way")for console application or a dialog for GUI apps. The default for the app type is not inferred from the PE image header, but rather from the type of entrypoint used (i.e. [w]main => console app, [w]WinMain). The dialog box caption "Visual C++" (and to a lesser extent the text) caused lots of confusion. For that reason, I had the honor to change the default to not showing that dialog/printing that message anymore in VC++10.
After that dialog, the CRT invokes the Windows Error Reporting (aka Watson). Whether or not that brings up a dialog box depends on the OS version and configuration. Typically, you would see it immediately as an administrator user on your interactive window station. If you're not, the report would be queued and an administrator would see it the next time logging on. If you have a debugger installed in the AeDebug key, you could get a chance to attach a debugger. But there have been a lot of changes again between different OS versions (e.g. the Auto key, UAC & restricted tokens etc.) The behavior of abort can be configured with _set_abort_behavior. WER has a ton of registry setting and a few APIs. Win7 API also gives you a great deal of control over error reporting. The story is a bit different for the debug builds of the CRT. The abort message is report via the debug interface. That's the same thing used for the assert and _ASSERT(E) macros. Their behavior can be configured with _CrtSetReport* functions. VC++ regressions test suites regularly install hooks to test things that result in a debug message. Long story short, to get rid of the "blah stopped working" you should call _set_abort_behavior(0,_CALL_REPORTFAULT) for release builds and _CrtSetReport* for debug builds (/MTd or /MDd) I hope I got that right -- that's all from quickly fading memory. I have been pretty much working on Linux only since I left Microsoft last summer. -hg

On Mon, Jan 17, 2011 at 4:38 PM, Jim Bell <Jim@jc-bell.com> wrote:
\HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\ForceQueue 1
I spent a few google iterations on that one, too. Other parameters have appealing-sounding names <http://msdn.microsoft.com/en-us/library/bb513638%28VS.85%29.aspx>, but don't seem to affect the pop-up.
Worked flawlessly! Many, many, thanks! --Beman

From: Beman Dawes BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert");
+1, although I hate the name - it's too long. The use of asserts should be encouraged by making them fast to type and cluttering the code as little as possible. Right now I can't think of any obviously good name, but maybe BOOST_ASSERTM (assert with message)? Best regards, RK

On 1/17/2011 10:24 PM, Robert Kawulak wrote:
From: Beman Dawes BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert");
+1, although I hate the name - it's too long. The use of asserts should be encouraged by making them fast to type and cluttering the code as little as possible. Right now I can't think of any obviously good name, but maybe BOOST_ASSERTM (assert with message)?
It should be BOOST_ASSERT_MSG, just as MPL has BOOST_MPL_ASSERT_MSG. And +1 to Dean's suggestion of std::abort. And also, can we find a better option than writing to std::cerr? And lastly, just as with BOOST_ASSERT, there should be a way to hook it to install your own failed-assertion handler. That is all. :-) -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Mon, Jan 17, 2011 at 10:42 AM, Eric Niebler <eric@boostpro.com> wrote:
On 1/17/2011 10:24 PM, Robert Kawulak wrote:
From: Beman Dawes BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert");
+1, although I hate the name - it's too long. The use of asserts should be encouraged by making them fast to type and cluttering the code as little as possible. Right now I can't think of any obviously good name, but maybe BOOST_ASSERTM (assert with message)?
It should be BOOST_ASSERT_MSG, just as MPL has BOOST_MPL_ASSERT_MSG.
Ha! Much better! Thanks!
And +1 to Dean's suggestion of std::abort.
Yeah, that's better if I can only figure out how to stop the [expletive deleted] Windows dialog boxes.
And also, can we find a better option than writing to std::cerr?
I really don't like std::cerr either, because it doesn't interleave correctly with cout on VC++ builds. What about changing to std::cout as the default of all of <boost/assert.hpp>, but with a configuration macro available to override the default?
And lastly, just as with BOOST_ASSERT, there should be a way to hook it to install your own failed-assertion handler.
Yeah, I assumed that, but didn't want to bother with it unless the basic idea of BOOST_ASSERT_MSG() flies.
That is all. :-)
Much help,
Thanks, --Beman

----- Original Message ----- From: "Eric Niebler" <eric@boostpro.com> To: <boost@lists.boost.org> Sent: Monday, January 17, 2011 4:42 PM Subject: Re: [boost] [assert] static_assert envy
On 1/17/2011 10:24 PM, Robert Kawulak wrote:
From: Beman Dawes BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert");
+1, although I hate the name - it's too long. The use of asserts should be encouraged by making them fast to type and cluttering the code as little as possible. Right now I can't think of any obviously good name, but maybe BOOST_ASSERTM (assert with message)?
It should be BOOST_ASSERT_MSG, just as MPL has BOOST_MPL_ASSERT_MSG. And +1 to Dean's suggestion of std::abort. And also, can we find a better option than writing to std::cerr? And lastly, just as with BOOST_ASSERT, there should be a way to hook it to install your own failed-assertion handler. That is all. :-)
+1 Vicente

On Mon, Jan 17, 2011 at 10:24 AM, Robert Kawulak <robert.kawulak@gmail.com>wrote:
From: Beman Dawes BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert");
+1, although I hate the name - it's too long. The use of asserts should be encouraged by making them fast to type and cluttering the code as little as possible. Right now I can't think of any obviously good name, but maybe BOOST_ASSERTM (assert with message)?
I didn't like it either, but didn't come up with anything better. But see Eric's later posting... --Beman

AMDG On 1/17/2011 7:06 AM, Beman Dawes wrote:
Whenever I write a BOOST_ASSERT macro, I'm envious of C++0x static_assert because of its ability to supply a clear error message. I'd really like to be able to write a variant of BOOST_ASSERT like this:
#include<boost/assert.hpp> int main() { BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert"); return 0; }
And then get debug mode output like this:
***** Internal Program Error - Assertion Failed ***** extended_assert_test.cpp(6): error in int main(void): This will assert
Adding the code below at the end of<boost/assert.hpp> will do just that. It isn't totally ready for prime time, but it would be nice to find out if others would like something similar added to<boost/assert.hpp>.
Is there anything wrong with the idiom assert(true && "This will not assert"); In Christ, Steven Watanabe

On Mon, Jan 17, 2011 at 11:57 AM, Steven Watanabe <watanabesj@gmail.com>wrote:
AMDG
Is there anything wrong with the idiom
assert(true && "This will not assert");
I've used that idiom, and sometimes is OK. But it depends too much on the compiler and platform. I'd rather get a uniform result.
--Beman

Den 17-01-2011 16:06, Beman Dawes skrev:
Whenever I write a BOOST_ASSERT macro, I'm envious of C++0x static_assert because of its ability to supply a clear error message. I'd really like to be able to write a variant of BOOST_ASSERT like this:
#include<boost/assert.hpp> int main() { BOOST_EXTENDED_ASSERT(true, "This will not assert"); BOOST_EXTENDED_ASSERT(false, "This will assert"); return 0; }
I'm fine with BOOST_ASSERT_MSG(). Since we are adding assert.hpp I would like to see BOOST_ASSERT_IF() BOOST_ASSERT_IF_MSG() as well. It is really much clearer to read and maintain than BOOST_ASSERT( !foo() || condition ); -Thorsten

On Tue, Jan 18, 2011 at 7:58 PM, Thorsten Ottosen <nesotto@cs.aau.dk> wrote:
I'm fine with BOOST_ASSERT_MSG().
+1 for BOOST_ASSERT_MSG().
Since we are adding assert.hpp I would like to see
BOOST_ASSERT_IF() BOOST_ASSERT_IF_MSG()
as well. It is really much clearer to read and maintain than
BOOST_ASSERT( !foo() || condition );
+1 -- Dean Michael Berris about.me/deanberris

On Tue, Jan 18, 2011 at 6:58 AM, Thorsten Ottosen <nesotto@cs.aau.dk> wrote:
...
I'm fine with BOOST_ASSERT_MSG(). Since we are adding assert.hpp I would like to see
BOOST_ASSERT_IF() BOOST_ASSERT_IF_MSG()
as well. It is really much clearer to read and maintain than
BOOST_ASSERT( !foo() || condition );
I like it! I'm working on a Boost quality implementation now. Stay tuned. Thanks, --Beman

Beman Dawes wrote:
On Tue, Jan 18, 2011 at 6:58 AM, Thorsten Ottosen <nesotto@cs.aau.dk> wrote:
...
I'm fine with BOOST_ASSERT_MSG(). Since we are adding assert.hpp I would like to see
BOOST_ASSERT_IF() BOOST_ASSERT_IF_MSG()
as well. It is really much clearer to read and maintain than
BOOST_ASSERT( !foo() || condition );
I like it!
I'm working on a Boost quality implementation now. Stay tuned.
Should there be BOOST_VERIFY variants also? Thanks for addressing this Beman. Jeff

On Tue, Jan 18, 2011 at 9:21 AM, Jeff Flinn <TriumphSprint2000@hotmail.com>wrote: Should there be BOOST_VERIFY variants also?
I don't know yet. Although it will be nice to have some additional functionality, <boost/assert.hpp> should remain simple enough that it can be absorbed by a new user in a few minutes.
Thanks for addressing this Beman.
Thanks to you and all the others providing ideas and feedback! --Beman

From: Thorsten Ottosen I'm fine with BOOST_ASSERT_MSG(). Since we are adding assert.hpp I would like to see
BOOST_ASSERT_IF() BOOST_ASSERT_IF_MSG()
as well. It is really much clearer to read and maintain than
BOOST_ASSERT( !foo() || condition );
And possibly BOOST_FAIL/BOOST_FAIL_MSG, equivalent to BOOST_ASSERT(false)/BOOST_ASSERT(false, msg)? Analogous method is found in .NET library and I happened to find it useful several times. Regards, Robert

Thorsten Ottosen wrote:
I'm fine with BOOST_ASSERT_MSG(). Since we are adding assert.hpp I would like to see
BOOST_ASSERT_IF() BOOST_ASSERT_IF_MSG()
as well.
Is that just an alternate spelling or is there something different about the usage and meaning?
It is really much clearer to read and maintain than
BOOST_ASSERT( !foo() || condition );
If you just mean s/BOOST_ASSERT/BOOST_ASSERT_IF/, it hardly matters given long exposure to assert() and many variants thereof. If you mean that, instead of what you showed above, you'd write the following, I don't see the value: BOOST_ASSERT_IF(!foo(), condition); Perhaps you mean that condition can be used to suppress certain assertions (and not others) without, itself, appearing in the assertion message? I've never done that, so the value is low for me, but perhaps there are good use cases I've overlooked. If you mean something else entirely, please clarify. _____ 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.

Den 18-01-2011 16:39, Stewart, Robert skrev:
Perhaps you mean that condition can be used to suppress certain assertions (and not others) without, itself, appearing in the assertion message? I've never done that, so the value is low for me, but perhaps there are good use cases I've overlooked.
If you mean something else entirely, please clarify.
It's to avoid writing BOOST_ASSERT( !foo() || assertion ) which in priciple is identical to if( foo() ) BOOST_ASSERT( assertion ) but which is not guaranteed to be removed by the compiler, whereas BOOST_ASSERT_IF( foo(), assertion ) is. -Thorsten

AMDG On 1/18/2011 9:06 AM, Thorsten Ottosen wrote:
Den 18-01-2011 16:39, Stewart, Robert skrev:
Perhaps you mean that condition can be used to suppress certain assertions (and not others) without, itself, appearing in the assertion message? I've never done that, so the value is low for me, but perhaps there are good use cases I've overlooked.
If you mean something else entirely, please clarify.
It's to avoid writing
BOOST_ASSERT( !foo() || assertion )
which in priciple is identical to
if( foo() ) BOOST_ASSERT( assertion )
but which is not guaranteed to be removed by the compiler, whereas
BOOST_ASSERT_IF( foo(), assertion )
What exactly is wrong with BOOST_ASSERT( !foo() || assertion ) or BOOST_ASSERT( foo() ? assertion : true ) IMHO, the last thing we need is lots of minor variations that don't add any real utility. In Christ, Steven Watanabe

On 1/19/2011 12:20 AM, Steven Watanabe wrote:
On 1/18/2011 9:06 AM, Thorsten Ottosen wrote:
It's to avoid writing
BOOST_ASSERT( !foo() || assertion )
which in priciple is identical to
if( foo() ) BOOST_ASSERT( assertion )
but which is not guaranteed to be removed by the compiler, whereas
BOOST_ASSERT_IF( foo(), assertion )
What exactly is wrong with BOOST_ASSERT( !foo() || assertion ) or BOOST_ASSERT( foo() ? assertion : true )
IMHO, the last thing we need is lots of minor variations that don't add any real utility.
+1 Less is more, -- Eric Niebler BoostPro Computing http://www.boostpro.com

2011/1/18 Steven Watanabe <watanabesj@gmail.com>:
What exactly is wrong with BOOST_ASSERT( !foo() || assertion ) or BOOST_ASSERT( foo() ? assertion : true )
IMHO, the last thing we need is lots of minor variations that don't add any real utility.
The utility here is communicativeness. Upon seeing: BOOST_ASSERT( !"we shouldn't get there" ); BOOST_ASSERT( condition && "this shouldn't happen" ); BOOST_ASSERT( !foo() || condition && "something is wrong" ); you have to turn your mind into a Karnaugh table for a while if you want to understand what this code does. OTOH: BOOST_FAIL_MSG( "we shouldn't get there" ); BOOST_ASSERT_MSG( condition, "this shouldn't happen" ); BOOST_ASSERT_IF_MSG( foo(), condition, "something is wrong" ); communicates the author's intention in a direct way and also makes it harder to make mistakes in the boolean expressions (note that foo and condition above may be boolean expressions themselves making the first technique quite error-prone). You could equally well ask what is the real utility of having C++-style casts over the C-style one. ;-) Best regards, Robert

Robert Kawulak wrote:
Sent: Tuesday, January 18, 2011 6:48 PM To: boost@lists.boost.org Subject: Re: [boost] [assert] static_assert envy
2011/1/18 Steven Watanabe <watanabesj@gmail.com>:
What exactly is wrong with BOOST_ASSERT( !foo() || assertion ) or BOOST_ASSERT( foo() ? assertion : true )
IMHO, the last thing we need is lots of minor variations that don't add any real utility.
The utility here is communicativeness. Upon seeing:
BOOST_ASSERT( !"we shouldn't get there" ); BOOST_ASSERT( condition && "this shouldn't happen" ); BOOST_ASSERT( !foo() || condition && "something is wrong" );
you have to turn your mind into a Karnaugh table for a while if you want to understand what this code does. OTOH:
I think there was already agreement that BOOST_ASSERT_MSG is a good thing.
BOOST_FAIL_MSG( "we shouldn't get there" );
I would prefer BOOST_ASSERT_MSG( false, "we shouldn't get there" ); so I don't need to think about the details of the differences between BOOST_FAIL_MSG and BOOST_ASSERT.
BOOST_ASSERT_MSG( condition, "this shouldn't happen" );
+1
BOOST_ASSERT_IF_MSG( foo(), condition, "something is wrong" );
I would prefer BOOST_ASSERT_MSG( !foo() || condition, "something is wrong" ); so I don't need to think about the details of the differences between BOOST_ASSERT_IF_MSG and BOOST_ASSERT. Regards, Thomas

2011/1/18 Thomas Klimpel <Thomas.Klimpel@synopsys.com>:
BOOST_FAIL_MSG( "we shouldn't get there" );
I would prefer BOOST_ASSERT_MSG( false, "we shouldn't get there" ); so I don't need to think about the details of the differences between BOOST_FAIL_MSG and BOOST_ASSERT.
It is a matter of taste, I'd rather use BOOST_FAIL_MSG here as more direct. As I said, I've been using .NET's Debug.Fail along Debug.Assert and I find it quite useful. It can also make the final message look a bit nicer – not something of big importance, but always.
BOOST_ASSERT_IF_MSG( foo(), condition, "something is wrong" );
I would prefer BOOST_ASSERT_MSG( !foo() || condition, "something is wrong" ); so I don't need to think about the details of the differences between BOOST_ASSERT_IF_MSG and BOOST_ASSERT.
Then consider a simple example: foo is: !c1.empty() && !c2.empty() condition is: c1.front() ? c2.front() : def_val() Now you have to compute !foo || condition, which is simple, but: 1) makes several opportunities for a mistake, 2) results in an expression that may be harder to decipher than the two initial expressions. And again, the resulting assert message can be nicer, too. We wouldn't be asking for those constructs if we weren't kept finding ourselves in situations where they would be indeed good to have. Best regards, RK

Robert Kawulak wrote:
2011/1/18 Thomas Klimpel wrote:
BOOST_ASSERT_IF_MSG( foo(), condition, "something is wrong" );
I would prefer BOOST_ASSERT_MSG( !foo() || condition, "something is wrong" ); so I don't need to think about the details of the differences between BOOST_ASSERT_IF_MSG and BOOST_ASSERT.
Then consider a simple example: foo is: !c1.empty() && !c2.empty() condition is: c1.front() ? c2.front() : def_val()
Now you have to compute !foo || condition, which is simple, but: 1) makes several opportunities for a mistake, 2) results in an expression that may be harder to decipher than the two initial expressions. And again, the resulting assert message can be nicer, too.
Perhaps let's also consider my argument "so I don't need to think about the details of the differences between BOOST_ASSERT_IF_MSG and BOOST_ASSERT" in more detail: The macro is named 'BOOST_ASSERT_IF_MSG' and takes three arguments. The last argument is clearly the message, as is easy to see from the usage. But is the first argument the condition that is asserted true, or the precondition for the assertion to be true. From the position of ASSERT in the name of the macro, I would guess that the first argument is the condition that is asserted true. However, from the way I would write it as "normal code" (if (foo()) assert(condition);), and because the precondition should come before the condition, I would guess that the first argument is the precondition for the assertion to be true. So I have to dig into the details of BOOST_ASSERT_IF_MSG and BOOST_ASSERT to understand the code. So back to your argument, that "BOOST_ASSERT_IF(..., ...)" is more readable than "BOOST_ASSERT(!(...)||(...))". Yes, you are right, if (...) { ... } else { ... } is often more readable than cryptic exclamation marks, question marks, brackets, ampersands and vertical dashes. This a good argument in favor of a "design by contract" library as Lorenzo Caminiti has developed (I think Thorsten Ottosen has also done work in this direction). But implementing a partial language with macros for some special cases isn't such a great thing, because it would just be another language that I would have to learn. If you stick with the logic expressions on the other hand, the language is already well known. Conclusion for me: There is a difference whether you 'assert(condition && "text message ingeniously included into a Boolean expression exploiting missing type safety");' is not great or whether you say 'assert(!(precondition)||(condition));' is not great. What we see here is really just the Boolean expression that is asserted to be true. It's not as readable as it could be, but the alternative is a proliferation of similar macros with slightly different behavior. Regards, Thomas

----- Original Message ----- From: "Thomas Klimpel" <Thomas.Klimpel@synopsys.com> To: <boost@lists.boost.org> Sent: Tuesday, January 18, 2011 9:31 PM Subject: Re: [boost] [assert] static_assert envy
Robert Kawulak wrote:
2011/1/18 Thomas Klimpel wrote:
BOOST_ASSERT_IF_MSG( foo(), condition, "something is wrong" );
I would prefer BOOST_ASSERT_MSG( !foo() || condition, "something is wrong" ); so I don't need to think about the details of the differences between BOOST_ASSERT_IF_MSG and BOOST_ASSERT.
Then consider a simple example: foo is: !c1.empty() && !c2.empty() condition is: c1.front() ? c2.front() : def_val()
Now you have to compute !foo || condition, which is simple, but: 1) makes several opportunities for a mistake, 2) results in an expression that may be harder to decipher than the two initial expressions. And again, the resulting assert message can be nicer, too.
Perhaps let's also consider my argument "so I don't need to think about the details of the differences between BOOST_ASSERT_IF_MSG and BOOST_ASSERT" in more detail:
The macro is named 'BOOST_ASSERT_IF_MSG' and takes three arguments. The last argument is clearly the message, as is easy to see from the usage. But is the first argument the condition that is asserted true, or the precondition for the assertion to be true. From the position of ASSERT in the name of the macro, I would guess that the first argument is the condition that is asserted true. However, from the way I would write it as "normal code" (if (foo()) assert(condition);), and because the precondition should come before the condition, I would guess that the first argument is the precondition for the assertion to be true. So I have to dig into the details of BOOST_ASSERT_IF_MSG and BOOST_ASSERT to understand the code.
So back to your argument, that "BOOST_ASSERT_IF(..., ...)" is more readable than "BOOST_ASSERT(!(...)||(...))". Yes, you are right, if (...) { ... } else { ... } is often more readable than cryptic exclamation marks, question marks, brackets, ampersands and vertical dashes. This a good argument in favor of a "design by contract" library as Lorenzo Caminiti has developed (I think Thorsten Ottosen has also done work in this direction). But implementing a partial language with macros for some special cases isn't such a great thing, because it would just be another language that I would have to learn. If you stick with the logic expressions on the other hand, the language is already well known.
Conclusion for me: There is a difference whether you
'assert(condition && "text message ingeniously included into a Boolean expression exploiting missing type safety");'
is not great or whether you say
'assert(!(precondition)||(condition));'
is not great. What we see here is really just the Boolean expression that is asserted to be true. It's not as readable as it could be, but the alternative is a proliferation of similar macros with slightly different behavior.
If we want to evaluate a condition when BOOST_DISABLE_ASSERTS is not defined we could add a macro BOOST_WHEN that can be used like BOOST_WHEN( !c1.empty() && !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); } and defined as #if defined(BOOST_DISABLE_ASSERTS) # define BOOST_WHEN( CND) if(true) {} else #else # define BOOST_WHEN( CND) if(!(CND)) {} else #endif Compared to BOOST_ASSERT((!( !c1.empty() && !c2.empty()) ||(c1.front() ? c2.front() : def_val())) && "something is wrong" ); is not shorter. It is just an alternative that avoids proliferation of similar macros and preserv readability. Best, Vicente

vicente.botet wrote:
If we want to evaluate a condition when BOOST_DISABLE_ASSERTS is not defined we could add a macro BOOST_WHEN that can be used like
BOOST_WHEN( !c1.empty() && !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); }
and defined as
#if defined(BOOST_DISABLE_ASSERTS) # define BOOST_WHEN( CND) if(true) {} else #else # define BOOST_WHEN( CND) if(!(CND)) {} else #endif
That's an interesting technique. I wondered before how Boost.Contract could achieve its tricks, but it probably doesn't even use this technique. However, wouldn't it be simpler to define #if defined(BOOST_DISABLE_ASSERTS) # define BOOST_ASSERT_CODE if(true) {} else #else # define BOOST_ASSERT_CODE if(false) {} else #endif and then write BOOST_ASSERT_CODE { if (!c1.empty() && !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); } } If a construct like this would be part of a Boost.Contract library, I certainly wouldn't object to it during a review. I'm not so sure whether I like it enough just of its own. But I certainly prefer it over BOOST_ASSERT_IF_MSG, because now I can write my assertion code in a language I already know, and it's just a single macro (more or less, we still have BOOST_DISABLE_ASSERTS and BOOST_ASSERT_MSG and all the related stuff). Regards, Thomas

AMDG On 1/18/2011 1:56 PM, Thomas Klimpel wrote:
That's an interesting technique. I wondered before how Boost.Contract could achieve its tricks, but it probably doesn't even use this technique. However, wouldn't it be simpler to define
#if defined(BOOST_DISABLE_ASSERTS) # define BOOST_ASSERT_CODE if(true) {} else #else # define BOOST_ASSERT_CODE if(false) {} else #endif
and then write
BOOST_ASSERT_CODE { if (!c1.empty()&& !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); } }
If a construct like this would be part of a Boost.Contract library, I certainly wouldn't object to it during a review. I'm not so sure whether I like it enough just of its own. But I certainly prefer it over BOOST_ASSERT_IF_MSG, because now I can write my assertion code in a language I already know, and it's just a single macro (more or less, we still have BOOST_DISABLE_ASSERTS and BOOST_ASSERT_MSG and all the related stuff).
There's really no need to get fancy. #ifndef BOOST_DISABLE_ASSERTS if (!c1.empty() && !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); } #endif works just fine. In Christ, Steven Watanabe

On 1/19/2011 8:21 AM, Steven Watanabe wrote:
There's really no need to get fancy.
#ifndef BOOST_DISABLE_ASSERTS if (!c1.empty() && !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); } #endif
works just fine.
My thoughts exactly. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
On 1/19/2011 8:21 AM, Steven Watanabe wrote:
There's really no need to get fancy.
#ifndef BOOST_DISABLE_ASSERTS if (!c1.empty() && !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); } #endif
works just fine.
My thoughts exactly.
Whether BOOST_ASSERTs are enabled is not solely controlled by BOOST_DISABLE_ASSERTS, so this is not quite correct.

Den 19-01-2011 17:35, Peter Dimov skrev:
Eric Niebler wrote:
On 1/19/2011 8:21 AM, Steven Watanabe wrote:
There's really no need to get fancy.
#ifndef BOOST_DISABLE_ASSERTS if (!c1.empty() && !c2.empty()) { BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" ); } #endif
works just fine.
My thoughts exactly.
Whether BOOST_ASSERTs are enabled is not solely controlled by BOOST_DISABLE_ASSERTS, so this is not quite correct.
which shows we don't want to write such messy code. -Thorsten

From: Thomas Klimpel So I have to dig into the details of BOOST_ASSERT_IF_MSG and BOOST_ASSERT to understand the code.
Yes, but you do it only once and from then on it's easy. On the contrary, with the longish boolean expressions you have to stop and think each time you encounter them to understand the code. After all, this is what abstraction in programming is all about - to give labels to common patterns to simplify their implementation and comprehension. You have to learn the labels, but then it's much easier to grasp the code. Best regards, Robert

On 01/18/2011 09:47 AM, Robert Kawulak wrote:
2011/1/18 Steven Watanabe<watanabesj@gmail.com>:
What exactly is wrong with BOOST_ASSERT( !foo() || assertion ) or BOOST_ASSERT( foo() ? assertion : true )
IMHO, the last thing we need is lots of minor variations that don't add any real utility. The utility here is communicativeness. Upon seeing:
BOOST_ASSERT( !"we shouldn't get there" ); BOOST_ASSERT( condition&& "this shouldn't happen" ); BOOST_ASSERT( !foo() || condition&& "something is wrong" );
you have to turn your mind into a Karnaugh table for a while if you want to understand what this code does. OTOH:
BOOST_FAIL_MSG( "we shouldn't get there" ); BOOST_ASSERT_MSG( condition, "this shouldn't happen" ); BOOST_ASSERT_IF_MSG( foo(), condition, "something is wrong" );
communicates the author's intention in a direct way and also makes it harder to make mistakes in the boolean expressions (note that foo and condition above may be boolean expressions themselves making the first technique quite error-prone). I find these exactly as prone to confusion and mistakes as the other. In each you have to stop for a minute and figure out what they mean, except with the first, it's normal boolean logic that you have to understand each day to program in C or C++. With the latter you have to first check your understanding of the idiom, understand what it implies and then slot each part into the resultant boolean expression. You end up at the same mental process either way.
I'm not saying that I'm against it, although I'd probably go with the naked assert as being clearer to any C/C++ programmer. Then they wouldn't have to learn another thing in order to be able to understand what I was talking about. I usually go as close to the basic language as possible for just that clarity. But that's just my style. If someone else wants to obfuscate a bit I don't mind it.
You could equally well ask what is the real utility of having C++-style casts over the C-style one. ;-) It's a bad analogy. The BOOST_FAIL_MSG and it's ilk just overlays another level of indirection. It adds more complexity. C++ style casts reduce complexity.
Best regards, Patrick

From: Patrick Horgan
You could equally well ask what is the real utility of having C++-style casts over the C-style one. ;-) It's a bad analogy. The BOOST_FAIL_MSG and it's ilk just overlays another level of indirection. It adds more complexity. C++ style casts reduce complexity.
I can't agree. The macros reduce complexity by simplifying the boolean expressions and by being more descriptive, thus better expressing the author's intention. And one could argue that C++ casts may add complexity as well, e.g. when you have const_cast<derived*>(dynamic_cast<const derived*>(const_base_ptr)) instead of (derived *) const_base_ptr Yet they are good, because, just like the macros, they tell more precisely what is done and will make it way harder to write something different than you intended. Regards, Robert

... elision by patrick and next quoted section by me ... It's a bad analogy. The BOOST_FAIL_MSG and it's ilk just overlays another level of indirection. It adds more complexity. C++ style casts reduce complexity. I can't agree. The macros reduce complexity by simplifying the boolean expressions and by being more descriptive, thus better expressing the author's intention. You have a certain logic, but what I meant was that BOOST_FAIL_MSG could be built in terms of BOOST_ASSERT. It adds another layer of indirection on top of it. And one could argue that C++ casts may add complexity as well, e.g. when you have
const_cast<derived*>(dynamic_cast<const derived*>(const_base_ptr))
instead of
(derived *) const_base_ptr The first uses simpler parts though, to accomplish what the more complex
Yet they are good, because, just like the macros, they tell more precisely what is done and will make it way harder to write something different than you intended. In the same way, you could build an old style cast on top of the foundation of the new style casts each of them being simpler than the
On 01/18/2011 04:07 PM, Robert Kawulak wrote: old style cast could do in one fell swoop. You've made my point, the old style cast is much more complex containing much meaning that leads to confusion and error often as not. It may _look_ simpler but it's because it's hiding complexity that you really have to consider anyway, or you'll regret it. old style cast. It's easy to see it the other way since the old style cast came first, but really it's like your BOOST_FAIL_MSG in that it could be built upon the lower level new style casts. (Or almost, there are things that you could do with an old-style cast that aren't legal with _any_ new style cast.) BOOST_FAIL_MSG would be like the old style cast in that is subsumes more intent without exposing it to you. Patrick

From: Patrick Horgan
I can't agree. The macros reduce complexity by simplifying the boolean expressions and by being more descriptive, thus better expressing the author's intention. You have a certain logic, but what I meant was that BOOST_FAIL_MSG could be built in terms of BOOST_ASSERT. It adds another layer of indirection on top of it.
Yes, it does. It seems like you're talking more about complexity of making the tool, while I talk about complexity of using the tool. For me, seeing and understanding a line with BOOST_ASSERT_IF_MSG would be way easier than the equivalent BOOST_ASSERT with the boolean expression. Similarly, BOOST_FAIL_MSG("msg") would be telling me what's happening at a glance while BOOST_ASSERT(!"msg") or BOOST_ASSERT_MSG(false, "msg") would require a little bit more time to parse.
And one could argue that C++ casts may add complexity as well, e.g. when you have
const_cast<derived*>(dynamic_cast<const derived*>(const_base_ptr))
instead of
(derived *) const_base_ptr The first uses simpler parts though, to accomplish what the more complex old style cast could do in one fell swoop. You've made my point, the old style cast is much more complex containing much meaning that leads to confusion and error often as not.
Now you've made my point. ;-) Using BOOST_ASSERT (C cast) to express all the kinds of assertions (type conversions) is more complex in the same sense as it may lead to confusion and errors. This is why I'd like to have these macros (C++ casts) - to have simpler, more specialised code-building blocks. It doesn't matter whether the simpler is implemented in terms of the more complex or the other way round - the effect is what counts.
BOOST_FAIL_MSG would be like the old style cast in that is subsumes more intent without exposing it to you.
I think exactly the opposite: BOOST_FAIL_MSG functionality is a subset of BOOST_ASSERT functionality, just like any C++ cast is a subset of the C cast. By using the less general tool you communicate your intention more precisely. Best regards, Robert

Den 18-01-2011 18:20, Steven Watanabe skrev:
AMDG
What exactly is wrong with BOOST_ASSERT( !foo() || assertion ) or BOOST_ASSERT( foo() ? assertion : true )
IMHO, the last thing we need is lots of minor variations that don't add any real utility.
I beg to differ. Code needs to be clear and meaningful to read, and the obscure rewrite rule makes the code harder to write and read. Simplifying logic is one of the best ways to simplify code and ensure it is correct. What is clear to experts might not be so clear to those of us that are mentally challenged when facing cryptic logic. As programmers we have enough other things to worry about. -Thorsten
participants (15)
-
Beman Dawes
-
Dean Michael Berris
-
Eric Niebler
-
Holger Grund
-
Jeff Flinn
-
Jim Bell
-
Mateusz Loskot
-
Patrick Horgan
-
Peter Dimov
-
Robert Kawulak
-
Steven Watanabe
-
Stewart, Robert
-
Thomas Klimpel
-
Thorsten Ottosen
-
vicente.botet