Reputation: 39859
I know that static_assert
makes assertions at compile time, and assert
- at run time, but what is the difference in practice? As far as I understand, deep down they are pieces of code, like
if (condition == false) exit();
static_assert
will work, or only assert
?if
statement can't do?Upvotes: 79
Views: 36718
Reputation: 361
It should be mentioned that it is important to find out about bugs as early as possible. A programmer wants to know when something first goes wrong, instead of the hundreds of problems caused by the original problem. If the code calculates a bad value and then uses it in subsequent calculations, all those calculations are wrong. Finding the earlies cause of the problem prevents the programmer from having to trace the bug back in time.
This is true for both run-time and compilation. Assert helps with this for run-time and static_assert helps with this for compilation. An example of where static_assert is useful for compile time checking to make sure the version of some header is perhaps equal to the version the rest of the code requires or was tested against. If the static_assert tells you the header version changed, it is much more useful than trying to figure out why you have all these compilation errors triggered by the changed header. It detects the problem as early as possible in the compilation process.
Another use for static_assert is to check whether the compilation was done with the right compiler switches. Microsoft's compilers, for example, use /J to signal that char be unsigned 8-bit value rather than signed. If the code requires it, it can be checked at compile time.
Upvotes: 0
Reputation: 49271
static_assert
is a compiler directive. It allows you to check type information at compile time. It will cause a compilation failure and produce an error message that in most IDE's be caught and displayed in the IDE's error window.
static_assert(sizeof(int) == 4,"int should be 4 bytes");
assert
is for runtime, you can check a variable's value. If the assertion fails then the assertion will trigger. This will cause an error message box that will appear at runtime in some Operating systems (assert implementation dependent)
assert(("mypointer should never be null!", mypointer != nullptr));
Upvotes: 5
Reputation: 33126
Is it bad practice to use them?
If abused, yes, particularly assert
.
One abuse is depending on those assert
statements to be active. You should never depend on assert
to do anything because the code can be compiled with NDEBUG
defined and then assert
does nothing. Production code is oftentimes compiled with NDEBUG
defined to ensure that those assert
statements disappear.
Unless you are writing a one-off program that won't live for more than a day or two, you shouldn't use to validate user input. Users don't care where the code failed, and the message that is printed looks like a foreign language to many users. It doesn't tell the user how to fix the error. It's also very unforgiving, by design. The message issued in response to a user input error should be a message that tells the user how to fix the problem. The best action after the message is to offer the user a way to fix the error. If that can't be done, and if the only viable response is to end the program, the program should terminate cleanly. By design, assert
does not result in a clean shutdown. It calls abort()
rather than exit()
.
One consequence of abort()
on many machines is to produce a core dump. A core dump is a great error message for a programmer. With a core dump, a programmer can use the debugger to see what went wrong in great detail. A downside of abort()
is that things aren't cleaned up. Abort "terminates the program without executing destructors for objects of automatic or static storage duration and without calling the functions passed to atexit()
."
Bottom line: It's okay (and good) to use assert
to test for programming errors, but only in a non-production setting. Use something else to test for user errors.
Upvotes: 5
Reputation: 5833
You ask three questions, so I will try to answer each of them.
static_assert
will work, or only assert
?static_assert
is good for testing logic in your code at compilation time. assert
is good for checking a case during run-time that you expect should always have one result, but perhaps could somehow produce an unexpected result under unanticipated circumstances. For example, you should only use assert
for determining if a pointer passed into a method is null
when it seems like that should never occur. static_assert
would not catch that.
if
statement can't do?assert
can be used to break program execution, so you could use an if
, an appropriate error message, and then halt program execution to get a similar effect, but assert
is a bit simpler for that case. static_assert
is of course only valid for compilation problem detection while an if
must be programmatically valid and can't evaluate the same expectations at compile-time. (An if
can be used to spit out an error message at run-time, however.)
Not at all!
Upvotes: 85
Reputation: 477514
OK, I'll bite:
Only static_assert
works if you want compilation to stop unsuccessfully if a static condition is violated: static_assert(sizeof(void*) != 3, "Wrong machine word size");
* Only dynamic assertions can catch dynamic conditions: assert(argc == 1);
Simple if
statements have to be valid and compilable; static assertions cause compilation failures.
No.
*) A practical example might be to prevent the abuse of generic template constructions, such as int x; std::move<int&&>(x)
.
Upvotes: 12
Reputation: 18236
static_assert
is meant to make compilation fail with the specified message, while traditional assert
is meant to end the execution of your program.
Upvotes: 33