ImFusion C++ SDK 4.5.0
Assertion Library

Assertion library. More...

Collaboration diagram for Assertion Library:

Detailed Description

Assertion library.

The Assertion Library provides more powerful and flexible alternative to the basic assert() of the C standard library. An assertion is a boolean predicate placed in code that should always evaluate to true when executed. This enables the programmer to encode assumptions in code, improve code readability, and enable the program to detect defects early.

We distinguish between two types of assertions that are syntactically very similar but have different semantic meanings and behave differently:

  • Debug Assertions are meant to implement optional run-time checks to ensure that programmer assumptions are met. However, the program execution may continue also in case of failure, and they are usually stripped from production builds.
  • Contract Assertions are meant to implement design-by-contract and are never optional. They are also present in production builds and regular program execution will abort in case of failure.
Note
Assertions are orthogonal to regular error handling and are not meant to replace it! They document logically impossible situations or documented preconditions/invariants of the code. If an assertion fails this means that something fundamental is wrong and either a programming error occurred, or some other unrecoverable error outside of the program's control.

Debug Assertions

Debug assertions implement optional run-time checks to ensure that programmer assumptions are met. The program execution may continue also in case of failure and their execution may even be disabled globally.

The debug assertion macro takes a condition to check and an optional message to display on failure.

class MyFile {
public:
MyClass(Filesystem::Path path)
: m_path(path.makeAbsolute())
{}
void compute()
{
// check the class invariant that the filesystem path is absolute
// if this assertion fails there must be an program execution path where this assumption is violated
IMFUSION_DEBUG_ASSERT(m_path.isAbsolute());
IMFUSION_DEBUG_ASSERT(m_path.isAbsolute(), "Path expected to be absolute");
// since we use a debug assertion it is fine to continue even if the assumption is not met
[...]
}
private:
Filesystem::Path m_path; // shall always be absolute
};
#define IMFUSION_DEBUG_ASSERT(...)
ImFusion debug assertion macro, supports two overloads:
Definition Assert.h:318

Assertions are only checked if IMFUSION_ENABLE_DEBUG_ASSERTIONS is defined for the preprocessor. By default, they are disabled for production release builds.

As a library developer you can register a custom debug assertion handler that should be called in case a debug assertion fails. The default debug assertion handler function will print an error message to std::cout and offer the user the choice of ignoring once, ignoring always, debug trap, or quitting the application.

Contract Assertions

Contract Assertions are non-optional run-time checks to implement design-by-contract. They will always be executed and regular program execution will abort in case of failure. They are primarily intended to enforce correctness guarantees.

The contract assertion macro takes a condition to check and an optional message to display on failure. They are supposed to used to check documented preconditions or invariants that are to be ensured by the programmer.

// Computes the square root.
// \param value The input *value* must not be negative
double mySqrt(double value)
{
IMFUSION_CONTRACT_ASSERT(value >= 0, "Input value must be positive");
return std::sqrt(value);
}
std::print("The sqrt of 4 is {0}\n", mySqrt(4.0)); // will print 2
std::print("The sqrt of -4 is {0}\n", mySqrt(-4.0)); // will abort execution
#define IMFUSION_CONTRACT_ASSERT(...)
ImFusion contract assertion macro, supports two overloads:
Definition Assert.h:351
T sqrt(T... args)

As a library developer you can register a custom contract assertion handler that should be called in case a contract assertion fails. The default contract assertion handler function will throw a ContractViolation exception.

Note
You can catch the ContractViolation exception at a high-level place in your application to gracefully abort computation and reset to a known valid state. You should not do this locally to simulate error handling. Having many catch sites for contract violations is an anti-pattern.

Namespaces

namespace  ImFusion::Assert
 Assertion library.

Classes

class  ImFusion::Assert::ContractViolation
 Represents a violation of a contract assertion. More...

Macros

#define IMFUSION_DEBUG_ASSERT(...)
 ImFusion debug assertion macro, supports two overloads:
#define IMFUSION_DEBUG_ASSERT_NOFUNCNAME(...)
 Variant of IMFUSION_DEBUG_ASSERT() that will forward an empty string as functionName to the registered HandlerFunction.
#define IMFUSION_CONTRACT_ASSERT(...)
 ImFusion contract assertion macro, supports two overloads:
#define IMFUSION_CONTRACT_ASSERT_NOFUNCNAME(...)
 Variant of IMFUSION_CONTRACT_ASSERT() that will forward an empty string as functionName to the registered HandlerFunction.

Typedefs

using ImFusion::Assert::HandlerFunction
 Alias for a function pointer that can be used to handle trapped assertions.

Functions

HandlerFunction ImFusion::Assert::debugAssertionHandler ()
 Returns the currently assigned handler function for debug asserts.
void ImFusion::Assert::setDebugAssertionHandler (HandlerFunction handler)
 Sets the debug assertion handler function to use.
void ImFusion::Assert::defaultDebugAssertionHandler (const char *condition, const char *message, const char *fileName, const char *functionName, int line)
 Handler function that is used by default to handle trapped debug assertions.
HandlerFunction ImFusion::Assert::handler ()
void ImFusion::Assert::setHandler (HandlerFunction handler)
 Sets the assertion handler function to use.
void ImFusion::Assert::defaultHandler (const char *condition, const char *message, const char *fileName, const char *functionName, int line)
 Handler function that is used by default to handle trapped assertions.
HandlerFunction ImFusion::Assert::contractAssertionHandler ()
 Returns the currently assigned handler function for contract asserts.
void ImFusion::Assert::setContractAssertionHandler (HandlerFunction handler)
 Sets the contract assertion handler function to use.
void ImFusion::Assert::defaultContractAssertionHandler (const char *condition, const char *message, const char *fileName, const char *functionName, int line)
 Handler function that is used by default to handle trapped contract assertions.

Macro Definition Documentation

◆ IMFUSION_DEBUG_ASSERT

#define IMFUSION_DEBUG_ASSERT ( ...)

#include <ImFusion/Core/Assert.h>

Value:
IMFUSION_ASSERT_EXPAND( \
IMFUSION_ASSERT_GET_MACRO(__VA_ARGS__, IMFUSION_DEBUG_ASSERT_2, IMFUSION_DEBUG_ASSERT_1)(__VA_ARGS__))

ImFusion debug assertion macro, supports two overloads:

IMFUSION_DEBUG_ASSERT(value > 0); // will trap if value is less or equal 0
IMFUSION_DEBUG_ASSERT(value > 0, "Need at least one item"); // will additionally print the message on failure

Debug assertions are only checked if IMFUSION_ENABLE_ASSERTIONS is defined.

See also
IMFUSION_DEBUG_ASSERT_NOFUNCNAME()

◆ IMFUSION_DEBUG_ASSERT_NOFUNCNAME

#define IMFUSION_DEBUG_ASSERT_NOFUNCNAME ( ...)

#include <ImFusion/Core/Assert.h>

Value:
IMFUSION_ASSERT_EXPAND(IMFUSION_ASSERT_GET_MACRO( \
__VA_ARGS__, IMFUSION_DEBUG_ASSERT_NOFUNCNAME_2, IMFUSION_DEBUG_ASSERT_NOFUNCNAME_1)(__VA_ARGS__))

Variant of IMFUSION_DEBUG_ASSERT() that will forward an empty string as functionName to the registered HandlerFunction.

This can help reducing binary bloat in templated header-only code where there are many different instantiations of the same template.

◆ IMFUSION_CONTRACT_ASSERT

#define IMFUSION_CONTRACT_ASSERT ( ...)

#include <ImFusion/Core/Assert.h>

Value:
IMFUSION_ASSERT_EXPAND( \
IMFUSION_ASSERT_GET_MACRO(__VA_ARGS__, IMFUSION_CONTRACT_ASSERT_2, IMFUSION_CONTRACT_ASSERT_1)(__VA_ARGS__))

ImFusion contract assertion macro, supports two overloads:

IMFUSION_CONTRACT_ASSERT(value > 0); // will trap if value is less or equal 0
IMFUSION_CONTRACT_ASSERT(value > 0, "Need at least one item"); // will additionally print the message on failure

Contract assertions will always be evaluated and abort local program execution if failed.

See also
IMFUSION_CONTRACT_ASSERT_NOFUNCNAME()

◆ IMFUSION_CONTRACT_ASSERT_NOFUNCNAME

#define IMFUSION_CONTRACT_ASSERT_NOFUNCNAME ( ...)

#include <ImFusion/Core/Assert.h>

Value:
IMFUSION_ASSERT_EXPAND(IMFUSION_ASSERT_GET_MACRO( \
__VA_ARGS__, IMFUSION_CONTRACT_ASSERT_NOFUNCNAME_2, IMFUSION_CONTRACT_ASSERT_NOFUNCNAME_1)(__VA_ARGS__))

Variant of IMFUSION_CONTRACT_ASSERT() that will forward an empty string as functionName to the registered HandlerFunction.

This can help reducing binary bloat in templated header-only code where there are many different instantiations of the same template.

Typedef Documentation

◆ HandlerFunction

#include <ImFusion/Core/Assert.h>

Initial value:
void (*)(const char* condition, const char* message, const char* fileName, const char* functionName, int line)

Alias for a function pointer that can be used to handle trapped assertions.

Parameters
conditionVerbatim code of the assertion condition that trapped.
messageMessage that was attached to the assertion.
fileNameFilename in which the assertion trapped.
functionNameFunction name where the assertion trapped.
lineLine number in fileName where the assertion trapped.

Function Documentation

◆ debugAssertionHandler()

HandlerFunction ImFusion::Assert::debugAssertionHandler ( )

#include <ImFusion/Core/Assert.h>

Returns the currently assigned handler function for debug asserts.

Note
This function returns global state.

◆ setDebugAssertionHandler()

void ImFusion::Assert::setDebugAssertionHandler ( HandlerFunction handler)

#include <ImFusion/Core/Assert.h>

Sets the debug assertion handler function to use.

Note
This function modifies global state.

◆ defaultDebugAssertionHandler()

void ImFusion::Assert::defaultDebugAssertionHandler ( const char * condition,
const char * message,
const char * fileName,
const char * functionName,
int line )

#include <ImFusion/Core/Assert.h>

Handler function that is used by default to handle trapped debug assertions.

Will offer the user the choice of ignoring once, ignoring always, debug trap, or quitting the application.

◆ handler()

HandlerFunction ImFusion::Assert::handler ( )
inline

#include <ImFusion/Core/Assert.h>

Note
This function returns global state.
Deprecated
Use debugAssertionHandler() instead.
Deprecated
"Use debugAssertionHandler() instead."

◆ setHandler()

void ImFusion::Assert::setHandler ( HandlerFunction handler)
inline

#include <ImFusion/Core/Assert.h>

Sets the assertion handler function to use.

Note
This function modifies global state.
Deprecated
Use setDebugAssertionHandler(HandlerFunction handler) instead.
Deprecated
"Use setDebugAssertionHandler(HandlerFunction) instead."

◆ defaultHandler()

void ImFusion::Assert::defaultHandler ( const char * condition,
const char * message,
const char * fileName,
const char * functionName,
int line )
inline

#include <ImFusion/Core/Assert.h>

Handler function that is used by default to handle trapped assertions.

Will offer the user the choice of ignoring once, ignoring always, debug trap, or quitting the application.

Deprecated
Use defaultDebugAssertionHandler(const char* condition, const char* message, const char* fileName, const char* functionName, int line) instead.
Deprecated
"Use defaultDebugAssertionHandler(...) instead."

◆ contractAssertionHandler()

HandlerFunction ImFusion::Assert::contractAssertionHandler ( )

#include <ImFusion/Core/Assert.h>

Returns the currently assigned handler function for contract asserts.

Note
This function returns global state.

◆ setContractAssertionHandler()

void ImFusion::Assert::setContractAssertionHandler ( HandlerFunction handler)

#include <ImFusion/Core/Assert.h>

Sets the contract assertion handler function to use.

handler must not be null.

Warning
The handler function must not return and has to abort current control flow. Resuming the regular execution of the calling function will yield undefined behavior.
Note
This function modifies global state.

◆ defaultContractAssertionHandler()

void ImFusion::Assert::defaultContractAssertionHandler ( const char * condition,
const char * message,
const char * fileName,
const char * functionName,
int line )

#include <ImFusion/Core/Assert.h>

Handler function that is used by default to handle trapped contract assertions.

Throws an exception of type ContractViolation.

Search Tab / S to search, Esc to close