Control-flow paths that should never execute can still appear in code for structural completeness. Compilers, however, cannot always decide that a specific branch is logically impossible. When such intent is not expressed explicitly, it may lead to less optimal code generation or unnecessary warnings.
Consider the following example with a scoped enumeration:
#include <iostream>
enum class Color { Red, Green, Blue };
const char *to_string(const Color c) {
switch (c) {
case Color::Red: return "Red";
case Color::Green: return "Green";
case Color::Blue: return "Blue";
default: return "";
}
}
int main() {
std::cout << to_string(Color::Red) << std::endl;
return 0;
}
All enumerators are handled in the switch statement. Logically, the default branch should never be selected. Nevertheless, the compiler cannot always guarantee that no other value will be passed, particularly in scenarios involving casts or undefined behavior. As a result, a fallback return statement is often added to satisfy control-flow requirements. Other projects achieve that in GCC and Clang using the compiler intrinsic __builtin_unreachable.
Since C++23, the standard library provides std::unreachable in the utility header. This function explicitly marks a code path as unreachable, clearly communicating developer intent to the compiler.
#include <iostream>
#include <utility>
enum class Color { Red, Green, Blue };
const char *to_string(const Color c) {
switch (c) {
case Color::Red: return "Red";
case Color::Green: return "Green";
case Color::Blue: return "Blue";
default: std::unreachable();
}
}
int main() {
std::cout << to_string(Color::Red) << std::endl;
return 0;
}
By replacing the dummy return statement with std::unreachable, the code becomes more expressive. The compilers may use this information to optimize generated machine code, since they can assume the marked path will never be executed.
Leave a Comment
Cancel reply