Better alternatives to assert(false) in C/C++
Replacing your assert(false)
is exactly what "unreachable" built-ins are for.
They are a semantic equivalent to your use of assert(false)
. In fact, VS's is spelt very similarly.
GCC/Clang/Intel:
__builtin_unreachable()
MSVS:
__assume(false)
These have effect regardless of NDEBUG
(unlike assert
) or optimisation levels.
Your compiler, particularly with the above built-ins but also possibly with your assert(false)
, nods its head in understanding that you're promising that part of the function will never be reached. It can use this to perform some optimisations on certain code paths, and it will silence warnings about missing returns because you've already promised that it was deliberate.
The trade-off is that the statement itself has undefined behaviour (much like going forth and flowing off the end of the function was already). In some situations, you may instead wish to consider throwing an exception (or returning some "error code" value instead), or calling std::abort()
(in C++) if you want to just terminate the program.
There's a proposal (P0627R0), to add this to C++ as a standard attribute.
From the GCC docs on Builtins:
If control flow reaches the point of the
__builtin_unreachable
, the program is undefined. It is useful in situations where the compiler cannot deduce the unreachability of the code. [..]
As a fully portable solution, consider this:
[[ noreturn ]] void unreachable(std::string_view msg = "<No Message>") {
std::cerr << "Unreachable code reached. Message: " << msg << std::endl;
std::abort();
}
The message part is, of course, optional.
I like to use
assert(!"This should never happen.");
...which can also be used with a condition, as in
assert(!vector.empty() || !"Cannot take element from empty container." );
What's nice about this is that the string shows up in the error message in case an assertion does not hold.