#pragma once #include #include #include #include #ifndef CLIO_WITHOUT_STACKTRACE #include #include #endif // CLIO_WITHOUT_STACKTRACE #include #include namespace util::impl { class OnAssert { public: using ActionType = std::function; private: static ActionType action; public: static void call(std::string_view message); static void setAction(ActionType newAction); static void resetAction(); private: static void defaultAction(std::string_view message); }; /** * @brief Assert that a condition is true * @note Calls std::exit if the condition is false * * @tparam Args The format argument types * @param location The location of the assertion * @param expression The expression to assert * @param condition The condition to assert * @param format The format string * @param args The format arguments */ template constexpr void assertImpl( std::source_location const location, char const* expression, bool const condition, fmt::format_string format, Args&&... args ) { if (!condition) { #ifndef CLIO_WITHOUT_STACKTRACE auto const resultMessage = fmt::format( "Assertion '{}' failed at {}:{}:\n{}\nStacktrace:\n{}", expression, location.file_name(), location.line(), fmt::format(format, std::forward(args)...), boost::stacktrace::to_string(boost::stacktrace::stacktrace()) ); #else auto const resultMessage = fmt::format( "Assertion '{}' failed at {}:{}:\n{}", expression, location.file_name(), location.line(), fmt::format(format, std::forward(args)...) ); #endif OnAssert::call(resultMessage); } } } // namespace util::impl #define ASSERT(condition, ...) \ util::impl::assertImpl( \ std::source_location::current(), #condition, static_cast(condition), __VA_ARGS__ \ )