Implement assert without preprocessor in C++20

Viewed 681

C++ knows assert() which allows runtime checks that compile to nothing in dependence of NDEBUG.

I would like to replace that macro using compiler-code and avoiding the preprocessor. I need to do the following:

  • Break or terminate if expressions evaluates to false
  • Log the code line where the assert is called
  • Discard the check and the passed expression for NDEBUG builds

Breaking/terminating the application is easy.

In C++20 there is std::experimental::source_location which I can use to get the code location of the assertion.

A compile time conditional could be done using requires or constexpr if

However I do not know how I could avoid the evaluation of the expression. When implementing myAssert(expression) as a function, I need to pass the expression result as a function argument which means it is evaluated anyway, even if the parameter is not used inside the function.

Is there a way to solve this in C++20?

EDIT: A templated example:

template <typename T> requires (gDebug)
void assertTrue(const T& pResult, const std::experimental::source_location& pLocation) noexcept
{
   if (!static_cast<bool>(pResult))
   {
      // error handling
   }
}

template <typename T> requires (!gDebug)
void assertTrue(const T&) noexcept
{
}
1 Answers

I suppose you are talking about the case when you disabled debugging and you want the function to be a noop. I see 2 options:

You can use a macro. Macros can be misused, but they have their place and "passing an expression" without evaluating it is a case for a macro.

Alternatively, pass a callable that returns the result you want to assert for. Only call it when gDebug == True:

template <typename F> requires (gDebug)
void assertTrue(const F& f, const std::experimental::source_location& pLocation) noexcept
{
   if (!static_cast<bool>(f()))
   {
      // error handling
   }
}

Though this will make the call rather verbose. For example one that fails always:

assertTrue( [](){ return false; });
Related