61 lines
3.1 KiB
C++
Raw Normal View History

#pragma once
#include "../macro/feature_probe.hpp"
#include <string_view>
#if defined(YYCC_CPPFEAT_FORMAT)
#include <format>
#endif
/**
* @brief Provides Rust-style panic functionality for immediate program termination on unrecoverable errors.
* @details
* This namespace provides macros and functions to handle unrecoverable errors in C++ code.
* It imitate Rust's \c panic! macro behavior, allowing the program to immediately exit with error information and stack traces.
*
* After writing programs in Rust, I deeply realized the necessity of handling errors immediately.
* When encountering unrecoverable errors, the program should exit immediately and report the error, which ensures program robustness.
* Therefore, I introduced this namespace and implemented macros and functions equivalent to Rust's \c panic! macro.
*
* Unfortunately, I cannot change the exception mechanism in the standard library.
* The standard library will still throw exceptions where it does, and I cannot prevent that.
* Therefore, I suggest a good practice that any C++ exception should be immediately treated as an error and cause the program to crash and exit.
* For this reason, registering any unhandled error callbacks which may resume the execution of program is prohibited to prevent unexpected continuation of execution.
* For code we write ourselves that we can control, we should use the macros provided in this file instead of throwing exceptions.
* In this way, unexpected behavior in our code will cause the program to exit immediately, outputting error information and stack traces.
* Standard library exceptions will also cause the program to exit, but without stack information.
*/
namespace yycc::rust::panic {
/**
* @brief Immediately crashes the entire program like Rust's \c panic! macro.
* @details The macro parameter is the additional message to display.
*/
#define RS_PANIC(msg) ::yycc::rust::panic::panic(__FILE__, __LINE__, (msg))
/**
* @brief Immediately crashes the entire program like Rust's \c panic! macro.
* @details
* The macro parameters are the message to format and its arguments, following \c std::format syntax.
* This macro essentially calls \c std::format internally.
*/
#if defined(YYCC_CPPFEAT_FORMAT)
#if defined(YYCC_CPPFEAT_VA_OPT)
#define RS_PANICF(msg, ...) RS_PANIC(std::format(msg __VA_OPT__(, ) __VA_ARGS__))
#else
#define RS_PANICF(msg, ...) RS_PANIC(std::format(msg, ##__VA_ARGS__))
#endif
#endif
/**
* @brief Immediately crashes the entire program like Rust's \c panic! macro.
* @details
* This is the actual crash output function called by the macros.
* The crash information will be written to \c stderr, including stack traces if your C++ runtime support it.
* @param[in] file Source file name where panic occurred. Usually filled by macros.
* @param[in] line Line number in source file where panic occurred. Usually filled by macros.
* @param[in] msg Message to display during panic.
*/
[[noreturn]] void panic(const char* file, int line, const std::string_view& msg);
} // namespace yycc::rust::panic