OMNI_FATAL_UNLESS

Defined in omni/core/Assert.h

OMNI_FATAL_UNLESS(cond_, ...)

This macro is surprisingly complex mainly because it accepts a variable number of arguments. If a single argument is given, a message in the following form is printed:

“Assertion (myCondition) failed.\n”

If multiple arguments are given, the message become more dynamic:

“Assertion (var == 1) failed: var == 2\n”

Where the latter part of the message “var == 2” is provided by the caller.

So, if multiple arguments are given, this macro must:

  • End the first part of the message with a : instead of an .

  • Concatenate the the fixed format string (“Assertion (%s)…””) with the user supplied format message.

  • Add a newline.

All of this at compile time.

We use a couple of tricks to do this (all in portable C++).

  • Via the preprocessor, we can’t detect if VA_ARGS is empty (this is a preprocessor limitation). We can forward the VA_ARGS to a constexpr (hasArg). hasArg is an overloaded constexpr that will return true if an argument was supplied. We can then use the result of this overload to select a template specialization (Assertion<>) containing a constexpr with our format string.

  • We need to concatenate the first part of the format string with the user provided portion and a newline. We can’t do this with the preprocess because the first part of the message is a constexpr, not a string literal. To get around this we use a constexpr (constConcat) to perform the concatenation.

  • The user format string may be empty. We use the preprocessor’s string concatenation in OMNI_VA_FIRST_OR_EMPTY_STRING to make sure a second argument is passed to the constexpr string concatenation function.

  • When passing the VA_ARGS to fprintf, we need to elide the first argument (since it’s the user supplied format we already concatenated) and provide a comma if any additional arguments were given. While the preprocessor cannot detect if VA_ARGS is empty, it can detect if at least two arguments are supplied. OMNI_VA_COMMA_WITHOUT_FIRST uses this to determine if a comma should be added and to elide the first user supplied argument (the user’s format string).

Some of this code can be simplified with C++20’s VA_OPT. Checks if the given condition is true, if not, the given optional message is printed to stdout and the program is terminated.

Use this macro when an unrecoverable situation has been detected.