Doc. no.: N3500
Reply to: Olaf van der Spek <firstname.lastname@example.org>
Title: New Assert Variants
This proposal introduces new variants of the existing assert() facility. The new variants serve use cases the original variant doesn't.
II. Motivation and Scope
The existing assert variant does not allow a message to be passed, this is sometimes worked around via assert(expression && "message"); The _msg variants provide a cleaner way to pass a message.
The existing variant does not evaluate the expression when NDEBUG is defined, so it can't be used for expressions with desirable side effects. Verify solves this.
The existing variant and verify do not check the expression when NDEBUG is defined, but in some cases that's desirable. For example: assure_msg(!fclose(os), "fclose() failed"); Assure solves this.
Assure aborts the program if the expression is false, but some use cases may demand an exception to be thrown instead. A fourth variant could be created to serve this use case if there's demand for this.
Boost provides BOOST_ASSERT, BOOST_ASSERT_MSG and BOOST_VERIFY, but no BOOST_VERIFY_MSG.
MFC provides ASSERT and VERIFY.
Poco provides poco_assert (throws) and poco_assert_dbg (throws but only if NDEBUG isn't defined)
Qt provides Q_ASSERT and Q_ASSERT_X (assert with message).
Assure is essentially the simplest form of error handling, especially useful in textbooks (instead of // handle errors here, or worse, ignoring errors) and rapid development. It's still useful in real programs where simple error handling suffices.
III. Impact on the Standard
The new variants (probably) depend on the existing assert variant. Nothing depends on the new variants. It's a pure extension and can be implemented using C++11 compilers and libraries.
IV. Design Decisions
The _msg variants are a natural extension of the existing variants. The names verify and assure are semi-arbitrary, better names might be available.
V. Technical Specifications
/* equivalent to assert(expression), except it also prints message (when expression is false) /*
/* equivalent to assert(expression), except it always evaluates expression, even when NDEBUG is defined */
/* equivalent to assert(expression), except it always evaluates and checks expression, even when NDEBUG is defined */