diff options
Diffstat (limited to 'src/zencore/include')
| -rw-r--r-- | src/zencore/include/zencore/assertfmt.h | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/zencore/include/zencore/assertfmt.h b/src/zencore/include/zencore/assertfmt.h new file mode 100644 index 000000000..56383ffd9 --- /dev/null +++ b/src/zencore/include/zencore/assertfmt.h @@ -0,0 +1,48 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <zencore/zencore.h> + +#include <fmt/args.h> +#include <string_view> + +namespace zen { + +namespace assert { + template<typename... T> + auto AssertCaptureArguments(T&&... Args) + { + return fmt::make_format_args(Args...); + } + + void ExecAssertFmt + [[noreturn]] (const char* Filename, int LineNumber, const char* FunctionName, std::string_view Format, fmt::format_args Args); + + // MSVC (v19.00.24215.1 at time of writing) ignores no-inline attributes on + // lambdas. This can be worked around by calling the lambda from inside this + // templated (and correctly non-inlined) function. + template<typename RetType = void, class InnerType, typename... ArgTypes> + RetType ZEN_FORCENOINLINE ZEN_DEBUG_SECTION CallColdNoInline(InnerType&& Inner, ArgTypes const&... Args) + { + return Inner(Args...); + } + +} // namespace assert + +#define ZEN_ASSERT_FORMAT(x, fmt, ...) \ + do \ + { \ + using namespace std::literals; \ + if (x) [[likely]] \ + break; \ + zen::assert::CallColdNoInline([&]() ZEN_FORCEINLINE { \ + zen::assert::ExecAssertFmt(__FILE__, \ + __LINE__, \ + __FUNCTION__, \ + "assert(" #x ") failed: " fmt ""sv, \ + zen::assert::AssertCaptureArguments(__VA_ARGS__)); \ + }); \ + } while (false) + +} // namespace zen |