export module preliminary.assertions; import preliminary.build_constants; import std; /////////////////////////////////////// // ----------* INTERFACE *--------- // ///////////////////////////////////// /** To be used for ensuring a condition holds true, throws otherwise. */ export template struct ensure { ensure( const Expression_T &expression, std::format_string fmt, Args_T &&...args, const std::source_location &location = std::source_location::current() ); }; /** To be used for costly checks that should be stripped in release builds. */ export template struct debug_check { debug_check( const Expression_T &expression, std::format_string fmt, Args_T &&...args, const std::source_location &location = std::source_location::current() ); }; export template ensure(Expression_T, std::format_string, Args_T &&...) -> ensure; export template debug_check(Expression_T, std::format_string, Args_T &&...) -> debug_check; /////////////////////////////////////// // * IMPLEMENTATION -- TEMPLATES * // ///////////////////////////////////// template ensure::ensure( const Expression_T &expression, std::format_string fmt, Args_T &&...args, const std::source_location &location ) { if (!static_cast(expression)) { throw std::runtime_error { std::format( "exception: {}\nlocation: {}:{}", std::format(fmt, std::forward(args)...), location.file_name(), location.line() ) }; } } template debug_check::debug_check( const Expression_T &expression, std::format_string fmt, Args_T &&...args, const std::source_location &location ) { if constexpr (build_constants::build_type != build_constants::BuildType::debug) { return; } if (!static_cast(expression)) { throw std::runtime_error { std::format( "exception: {}\nlocation: {}:{}", std::format(fmt, std::forward(args)...), location.file_name(), location.line() ) }; } }