diff --git a/rx/include/rx/die.hpp b/rx/include/rx/die.hpp index 56e6c6bc1..552aee594 100644 --- a/rx/include/rx/die.hpp +++ b/rx/include/rx/die.hpp @@ -1,26 +1,31 @@ #pragma once #include "format-base.hpp" +#include +#include namespace rx { +using DieHandler = + std::function; + +void setDieHandler(DieHandler handler); + namespace detail { [[noreturn]] void dieImpl(std::string_view fmt, format_args args, std::source_location location); } template -[[noreturn]] void die(rx::format_string_with_location fmt, +[[noreturn]] void die(format_string_with_location fmt, const Args &...args) { - detail::dieImpl(fmt.get(), make_format_args(const_cast(args)...), - fmt.location); + detail::dieImpl(fmt.get(), rx::make_format_args(args...), fmt.location); } template -void dieIf(bool condition, rx::format_string_with_location fmt, +void dieIf(bool condition, format_string_with_location fmt, const Args &...args) { if (condition) { - detail::dieImpl(fmt.get(), make_format_args(const_cast(args)...), - fmt.location); + detail::dieImpl(fmt.get(), rx::make_format_args(args...), fmt.location); } } } // namespace rx diff --git a/rx/include/rx/format-base.hpp b/rx/include/rx/format-base.hpp index 57d5029c8..3f81a4220 100644 --- a/rx/include/rx/format-base.hpp +++ b/rx/include/rx/format-base.hpp @@ -41,15 +41,27 @@ struct format_string_impl : fmt::format_string { return std::string_view(this->str); } }; + +template struct make_format_arg_type { + using type = T &; +}; + +template + requires requires(const T &arg) { fmt::make_format_args(arg); } +struct make_format_arg_type { + using type = const T &; +}; + } // namespace detail template using format_string = std::type_identity_t>; template -auto make_format_args(const Args &...args) - -> decltype(fmt::make_format_args(const_cast(args)...)) { - return fmt::make_format_args(const_cast(args)...); +auto make_format_args(const Args &...args) -> decltype(fmt::make_format_args( + const_cast::type>(args)...)) { + return fmt::make_format_args( + const_cast::type>(args)...); } using fmt::format_to; diff --git a/rx/include/rx/refl.hpp b/rx/include/rx/refl.hpp index 9662ce79f..bba608587 100644 --- a/rx/include/rx/refl.hpp +++ b/rx/include/rx/refl.hpp @@ -173,6 +173,8 @@ constexpr auto calcFieldCount() { return static_cast(EnumT::_count); } else if constexpr (requires { EnumT::count; }) { return static_cast(EnumT::count); + } else if constexpr (requires { EnumT::_last; }) { + return static_cast(EnumT::_last) + 1; } else if constexpr (!requires { getNameOf()[0]; }) { if constexpr (requires { getNameOf()[0]; }) { if constexpr (constexpr auto c = getNameOf()[0]; diff --git a/rx/src/die.cpp b/rx/src/die.cpp index 776ab45a0..62da2b6e0 100644 --- a/rx/src/die.cpp +++ b/rx/src/die.cpp @@ -1,18 +1,35 @@ #include "die.hpp" +#include "print.hpp" +#include "format-base.hpp" + #include #include -#include + + +static rx::DieHandler g_dieHandler; + +void rx::setDieHandler(DieHandler handler) { + g_dieHandler = std::move(handler); +} void rx::detail::dieImpl(std::string_view fmt, format_args args, std::source_location location) { - rx::print(stderr, "\n"); - rx::print(stderr, "{}:{}:{}: ", location.file_name(), location.line(), - location.column()); - rx::vprint_nonunicode(stderr, fmt, args); - rx::print(stderr, "\n"); + if (g_dieHandler != nullptr) { + rx::print(stderr, "\n"); + std::fflush(stdout); + std::fflush(stderr); + + g_dieHandler(rx::vformat(fmt, args), location); + } else { + rx::print(stderr, "\n"); + rx::print(stderr, "{}:{}:{}: ", location.file_name(), location.line(), + location.column()); + rx::vprint_nonunicode(stderr, fmt, args); + rx::print(stderr, "\n"); + std::fflush(stdout); + std::fflush(stderr); + } - std::fflush(stdout); - std::fflush(stderr); std::abort(); }