I can imagine two implementations of die, and I have issue with both of them
template <typename... Ts>
[[noreturn]] inline bool die(std::string_view message_format = "", Ts&&... args)
{
std::cerr << std::vformat(message_format, std::make_format_args(args...));
std::abort(); // or std::exit or std::terminate
}
That is, write the message somewhere and end the program. I could imagine a project using this, but not the projects I'm involved in.
It seems most appropriate in projects large enough that you don't just return up to main, but small enough that killing the whole process is never overkill.
template <typename... Ts>
[[noreturn]] inline bool die(std::string_view message_format = "", Ts&&... args)
{
throw std::runtime_error(std::vformat(message_format, std::make_format_args(args...)));
}
I.e. throw a generic exception, with the message. I would prefer some granularity in the type of the exception, so that args... could instead be a data member for the catch. If pressed, i'd write that as
template<typename T, typename... Args>
[[noreturn]] inline bool die_with(Args&&... args)
{
throw T(std::forward<Args>(args)...);
}
things_are_ok() or die_with<things_exception>("things not ok", foo);
But there are other ways of massaging a throw to be a bool expression
things_are_ok() or (throw things_exception("things not ok", foo), false);