diff --git a/cpp/07-exceptions-and-raii/2023-11-24-placeholders.md b/cpp/07-exceptions-and-raii/2023-11-24-placeholders.md index a7f4c15..1c4383f 100644 --- a/cpp/07-exceptions-and-raii/2023-11-24-placeholders.md +++ b/cpp/07-exceptions-and-raii/2023-11-24-placeholders.md @@ -203,3 +203,20 @@ void unreachable(std::format_string fmt, Args&&... args) { Final source code: [`placeholders.hpp`](pathname:///files/cpp/exceptions-and-raii/placeholders/placeholders.hpp) ::: + +## Post-mortem + +One of the things, I've forgotten about, is the fact that static analysis of +your code has no way to know those helper functions we've created as shortcuts +don't return and just throw the exception right away. Therefore we need to mark +them with `[[noreturn]]` to let the static analysis know that we **never** +return from such functions. For example: + +```cpp +[[noreturn]] void unreachable() { throw _unreachable(); } + +template +[[noreturn]] void unreachable(std::format_string fmt, Args&&... args) { + throw _unreachable(std::format(fmt, args...)); +} +``` diff --git a/static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp b/static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp index 9ffbf8c..8a7d6be 100644 --- a/static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp +++ b/static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp @@ -14,7 +14,7 @@ class _todo : public std::exception { /** * @brief Indicates unfinished code. */ -void todo() { throw _todo(); } +[[noreturn]] void todo() { throw _todo(); } /** * @brief Indicates unfinished code. @@ -22,7 +22,7 @@ void todo() { throw _todo(); } * @param args arguments to be formatted */ template -void todo(std::format_string fmt, Args&&... args) { +[[noreturn]] void todo(std::format_string fmt, Args&&... args) { throw _todo(std::format(fmt, args...)); } @@ -39,7 +39,7 @@ class _unimplemented : public std::exception { /** * @brief Indicates unimplemented code by throwing with a message of “not implemented”. */ -void unimplemented() { throw _unimplemented(); } +[[noreturn]] void unimplemented() { throw _unimplemented(); } /** * @brief Indicates unimplemented code by throwing with a message of “not implemented”. @@ -47,7 +47,7 @@ void unimplemented() { throw _unimplemented(); } * @param args arguments to be formatted */ template -void unimplemented(std::format_string fmt, Args&&... args) { +[[noreturn]] void unimplemented(std::format_string fmt, Args&&... args) { throw _unimplemented(std::format(fmt, args...)); } @@ -64,7 +64,7 @@ class _unreachable : public std::exception { /** * @brief Indicates unreachable code. */ -void unreachable() { throw _unreachable(); } +[[noreturn]] void unreachable() { throw _unreachable(); } /** * @brief Indicates unreachable code. @@ -72,6 +72,6 @@ void unreachable() { throw _unreachable(); } * @param args arguments to be formatted */ template -void unreachable(std::format_string fmt, Args&&... args) { +[[noreturn]] void unreachable(std::format_string fmt, Args&&... args) { throw _unreachable(std::format(fmt, args...)); }