views:

95

answers:

3

Hallo!

I'm looking for a way to add custom messages to assert statements. I found this questions http://stackoverflow.com/questions/3692954/add-custom-messages-in-assert but the message is static there. I want to do something like this:

assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));

When the assertion fails I want the normal output plus for example "x was 100".

+6  A: 

You are out of luck here. The best way is to define your own assert macro.

Basically, it can look like this:

#ifndef NDEBUG
#   define ASSERT(condition, message) \
    do { \
        if (! (condition)) { \
            std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
                      << " line " << __LINE__ << ": " << message << std::endl; \
            std::exit(EXIT_FAILURE); \
        } \
    } while (false)
#else
#   define ASSERT(condition, message) do { } while (false)
#endif

This will define the ASSERT macro only if the no-debug macro NDEBUG isn’t defined.

Then you’d use it like this:

ASSERT((0 < x) && (x < 10), "x was " << x);

Which is a bit simpler than your usage since you don’t need to stringify "x was " and x explicitly, this is done implicitly by the macro.

Konrad Rudolph
Why the do { } while (false) ?
tauran
@tauran: So you can put a semicolon after the macro when using it.
Georg Fritzsche
Why not a `do { } while (false)` for the `#else` case? ;-) Also often useful to display the stringified assertion source code `#condition`. Strictly, EXIT_FAILURE should be preferred over 1 too. +1 as it's shaping up as the best answer.
Tony
@Tony: because I’m stupid.
Konrad Rudolph
Am I wrong in thinking that `asm("int 3")` is more appropriate for an assert macro than `exit()`?
Jon Purdy
Probably not so much `asm("int 3")`, but `abort()` might be better.
spong
@Jon: depends. Keep in mind that the `asm` one isn't portable (and on a MS compiler, won't even work in 64-builds), but also that depending on when, where and how you run the code, you might not want it to trigger a breakpoint. (MS has the `__debugbreak` intrinsic though, which works on all MS platforms) Ideally, you could make the macro configurable, so the developer can switch between aborting and breaking on assert at compile-time or at runtime
jalf
+2  A: 
#define ASSERT_WITH_MESSAGE(condition, message) do { \
if (!(condition)) { printf((message)); } \
assert ((condition)); } while(false)
Jon Rodriguez
+3  A: 

A better alternative is to teach the debugger to stop on assert when it fails, then you could examine not only the x value but any other information including call stack. Perhaps, this is what you are really looking for. Sample implementation is mentioned here http://stackoverflow.com/questions/3314314/ways-to-show-your-co-programmers-that-some-methods-are-not-yet-implemented-in-a-c/3316954#3316954

Alsk
+1 Not what I looked for, but could be really useful some day.
tauran