73

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();
  • Can someone give me an example of where only static_assert will work, or only assert?
  • Do they do anything a simple if statement can't do?
  • Is it bad practice to use them?
Oleksiy
  • 37,477
  • 22
  • 74
  • 122
  • `static_assert` is a declaration, built in to the core language. It doesn't expand to anything because if it doesn't succeed, the compilation stops. – jrok Aug 13 '13 at 13:25
  • 9
    @KerrekSB I asked **three** clear questions, please take time to read them before making an assumption – Oleksiy Aug 13 '13 at 13:25
  • 1
    You use assert to specify that there is an error in your programming logic and that it should be fixed in code. an `if` is used to branch between different logical paths in code. This is a big difference – default Aug 13 '13 at 13:30
  • to phrase it differently, `assert` is used to find invalid input, `if` is used to handle valid input. – default Aug 13 '13 at 13:34
  • 3
    There is one detail that has not been mentioned: `assert` does nothing if the `NDEBUG` macro is set. – juanchopanza Aug 13 '13 at 13:47
  • 2
    `assert` should never be used to validate input. – David Hammen Aug 13 '13 at 13:58
  • 1
    Another detail that has not been mentioned: `assert (expression)` results in a call to `abort()` rather than `exit()` if the expression is false. – David Hammen Aug 13 '13 at 14:16

6 Answers6

78

You ask three questions, so I will try to answer each of them.

  • Can someone give me an example of where only 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.

  • Do they do anything a simple 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.)

  • Is it bad practice to use them?

Not at all!

pattivacek
  • 5,617
  • 5
  • 48
  • 62
  • 4
    Good answer, however, adding that assert (the run-time variant) only works in debug builds and is a noop in release is probably a good idea. Which can be good, over an if statement, with extensive debug testing, to remove some possibly superfluous error checking optimizing for release builds. Also a warning to consider not putting state changing logic in the parenthesis of an assert, as the resulting logic will not exist in release builds... thus with assert( x++ < 12 ) for example, the x++ wont exist in release builds, only in debug. – Kit10 Jul 13 '16 at 18:06
31

static_assert is meant to make compilation fail with the specified message, while traditional assert is meant to end the execution of your program.

Nicola Musatti
  • 17,834
  • 2
  • 46
  • 55
  • .. and if you can get your failure to show up at compile time instead of runtime, that's a win. .. and is basically the entire reason I use languages with compile-time type checking. – orion elenzil Nov 10 '21 at 21:51
11

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).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
5

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.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
4

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));
Proxy
  • 1,824
  • 1
  • 16
  • 27
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
  • 1
    The assert macro defined in `` does not take two arguments – Joe Aug 13 '13 at 13:27
  • 5
    Although your question gives the right idea, there **(a)** is no error window with the compiler (it's part of an IDE if you use one that is kind enough to output compiler errors in a separate window) and **(b)** there is not necessarily an error message box when an assertion fails (it depends on the compiler, the OS and the runtime environment). – Arne Mertz Aug 13 '13 at 13:30
  • @ArneMertz was about to mention that as well – Joe Aug 13 '13 at 13:31
0

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.

Paul Topping
  • 341
  • 2
  • 10