diff --git a/src/utils/error.hpp b/src/utils/error.hpp index 0e3e3ff..fb82221 100644 --- a/src/utils/error.hpp +++ b/src/utils/error.hpp @@ -54,11 +54,11 @@ namespace detail { const char* expression, const char* signature, source_location location, - const std::string& message = "" + const char* message ) { const char* action = assert_actions[static_cast::type>(type)]; const char* name = assert_names[static_cast::type>(type)]; - if(message == "") { + if(message == nullptr) { throw internal_error( "Cpptrace {} failed at {}:{}: {}\n" " {}({});\n", @@ -69,7 +69,7 @@ namespace detail { throw internal_error( "Cpptrace {} failed at {}:{}: {}: {}\n" " {}({});\n", - action, location.file, location.line, signature, message.c_str(), + action, location.file, location.line, signature, message, name, expression ); } @@ -100,25 +100,13 @@ namespace detail { #define PHONY_USE(E) (nullfn()) - // Workaround a compiler warning + // Work around a compiler warning template bool as_bool(T&& value) { return static_cast(std::forward(value)); } - // Check condition in both debug and release. std::runtime_error on failure. - #define VERIFY(c, ...) ( \ - (::cpptrace::detail::as_bool(c)) \ - ? static_cast(0) \ - : (::cpptrace::detail::assert_fail)( \ - ::cpptrace::detail::assert_type::verify, \ - #c, \ - CPPTRACE_PFUNC, \ - {}, \ - ##__VA_ARGS__) \ - ) - - // Workaround a compiler warning + // Work around a compiler warning template std::string as_string(T&& value) { return std::string(std::forward(value)); @@ -131,17 +119,47 @@ namespace detail { // Check condition in both debug and release. std::runtime_error on failure. #define PANIC(...) ((::cpptrace::detail::panic)(CPPTRACE_PFUNC, {}, ::cpptrace::detail::as_string(__VA_ARGS__))) + template + void assert_impl( + T condition, + const char* message, + assert_type type, + const char* args, + const char* signature, + source_location location + ) { + if(as_bool(condition)) { + assert_fail(type, args, signature, location, message); + } + } + + template + void assert_impl( + T condition, + assert_type type, + const char* args, + const char* signature, + source_location location + ) { + assert_impl( + condition, + nullptr, + type, + args, + signature, + location + ); + } + + // Check condition in both debug and release. std::runtime_error on failure. + #define VERIFY(...) ( \ + assert_impl(__VA_ARGS__, ::cpptrace::detail::assert_type::verify, #__VA_ARGS__, CPPTRACE_PFUNC, {}) \ + ) + #ifndef NDEBUG // Check condition in both debug. std::runtime_error on failure. - #define ASSERT(c, ...) ( \ - (::cpptrace::detail::as_bool(c)) \ - ? static_cast(0) \ - : (::cpptrace::detail::assert_fail)( \ - ::cpptrace::detail::assert_type::assert, \ - #c, \ - CPPTRACE_PFUNC, \ - {}, \ - ##__VA_ARGS__) \ + #define ASSERT(...) ( \ + assert_impl(__VA_ARGS__, ::cpptrace::detail::assert_type::assert, #__VA_ARGS__, CPPTRACE_PFUNC, {}) \ ) #else // Check condition in both debug. std::runtime_error on failure. diff --git a/src/utils/microfmt.hpp b/src/utils/microfmt.hpp index 1db770e..572f26d 100644 --- a/src/utils/microfmt.hpp +++ b/src/utils/microfmt.hpp @@ -214,7 +214,7 @@ namespace microfmt { std::string str; std::size_t arg_i = 0; auto it = fmt_begin; - auto peek = [&] (std::size_t dist = 1) -> char { // 0 on failure + auto peek = [&] (std::size_t dist) -> char { // 0 on failure if(it != fmt_end) { return *(it + dist); } else { @@ -236,7 +236,7 @@ namespace microfmt { }; while(it != fmt_end) { if(*it == '{') { - if(peek() == '{') { + if(peek(1) == '{') { // try to handle escape str += '{'; it++; @@ -255,7 +255,7 @@ namespace microfmt { if(width != -1) { options.width = width; } else if(*it == '{') { // try to parse variable width - MICROFMT_ASSERT(peek() == '}'); + MICROFMT_ASSERT(peek(1) == '}'); it += 2; MICROFMT_ASSERT(arg_i < args.size()); options.width = args[arg_i++].unwrap_int(); @@ -285,7 +285,7 @@ namespace microfmt { } } else if(*it == '}') { // parse }} escape - if(peek() == '}') { + if(peek(1) == '}') { str += '}'; it++; } else {