top | item 33531141

(no title)

carstimon | 3 years ago

Undefined behavior is considered worse than crashing, which is typically the alternative when reaching "unreachable" codepaths.

Compare these two blocks similar to the article

   switch (ch) {
   case 'a': do_a(); return;
   case 'd': do_d(); return;
   // ch is guaranteed to be 'a' or 'd' by previous code.
   default: assert(0);
   }

   switch (ch) {
   case 'a': do_a(); return;
   case 'd': do_d(); return;
   default: std::unreachable();
   }

If the programmer is wrong about `ch` in the first one, the program terminates. For the second one, the compiler could change it to be equivalent to

  if (ch == 'a') { do_a(); }
  else { do_d(); }
  return;
If the programmer is wrong here, the program might `do_d()` with unintended consequences. I'd say "going down unintended codepaths" is typically considered worse than crashing.

N.b. fixed last code example- thanks afiori.

discuss

order

mannykannot|3 years ago

I take your point, but you can get the behavior of your first example, while still marking the default branch with std::unreachable(), by asserting the preconditions before the switch. This seems to me to be a pretty general equivalence.

So what does std::unreachable() do here? In this particular case, and with NDEBUG defined and any level of optimization selected, I suspect that, at a minimum, the switch would be replaced as you have shown in all versions - it would take a more complex example to show how std::unreachable() makes a difference. The point is, now we have a choice - and it is one that is being offered without creating any backwards-compatibility issues.

Furthermore, the original function, without assertions, is not guaranteed to crash, with or without std::unreachable(). You need some explicit checks to get a desirable response in the case where a mistake has been made, and that option is just as available whether or not you use std::unreachable().

Therefore, while I agree you have shown that not all broken variants of a given program are equivalent, this does not show that std::unreachable() is harmful.

afiori|3 years ago

I suspect you meant to omit the `if (c == 'd')` part in the last example

randomNumber7|3 years ago

I get your point, but assert is usually removed in release builds. Abort would probably be better if you want to crash the program.