jeremy-rifkin / libassert

The most over-engineered C++ assertion library
MIT License
539 stars 36 forks source link

ASSERT or variant returning result of the expression (not just left-hand operand) #101

Open StenSoft opened 2 months ago

StenSoft commented 2 months ago

Hi,

One thing that I currently use pretty often (especially for networking code) is:

if (!AssertTrue(a > 3)) {
    // Handle the failed assertion in release
    return;
}

This allows crashing in debug builds during testing but handling it without crashing for users in release builds.

It looks very similar to:

if (!ASSERT_VAL(a > 3))

but ASSERT_VAL returns the value of a, not the result of the whole expression a > 3.

Obviously it's possible to do

if (ASSERT_VAL(a > 3) <= 3)

but that makes it complicated and error-prone.

Would it be possible to return the result of the whole expression from ASSERT, or to create a variant of the macro (e.g. ASSERT_THAT) that returns the result?

jeremy-rifkin commented 2 months ago

Thanks for opening this, One thing I'm thinking about here is the line is between assertions and error handling. Generally assertions should be used for preconditions/postconditions, where violation constitutes a logical error from which execution cannot safely proceed. In this case and the #100 issue it looks like execution is possible after the condition violation.

I'd be interested in your thoughts.

I definitely agree on if (ASSERT_VAL(a > 3) <= 3) not being ideal.

StenSoft commented 2 months ago

My code runs distributed on many nodes in a network. In debug (or checked) builds, I want to make it obvious when there's a communication problem which should never happen in correct code and on reliable network but in release builds, I want it to be able to handle any data so that network problems or crashes of some devices (or malicious actors) won't bring the whole network down. I guess this is still error handling, not assertions (the node itself can recover), but error handling that in debug builds behaves just like failed assertions and produces core dumps so that the exact state can be analysed in detail, and in release build optimises the code so that the failure paths are marked [[unlikely]] (or __builtin_expect(…, false)) and logged with all the details that libassert can provide.