Чтобы получить больше информации, чем традиционный макрос assert
в c, я реализовал свой собственный макрос better_assert
, предоставив возможность печатать дополнительную отладочную информацию.
Таким образом, можно заменить
assert( a == b );
на
better_assert( a == b, "Error: expect a == b, but a = ", a, " and b = ", b );
Код реализации выглядит так:
constexpr int debug_mode = 1;
namespace xxxxxxxx
{ // for macro `better_assert`
template< typename... Args >
void print_assertion(std::ostream& out, Args&&... args)
{
if constexpr( debug_mode )
{
out.precision( 20 );
(out << ... << args) << std::endl;
abort();
}
}
}
#ifdef better_assert
#undef better_assert
#endif
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
с кодом тестированиянапример
int a = 1;
int b = 2;
better_assert( a == 1 );
better_assert( a == b, "Error: expected a == b, but a = ", a, " and b = ", b );
gcc 9.1.0 принимает этот код без проблем, но clang 8.0.0 отклонил его с сообщением об ошибке:
prog.cc:28:5: error: expected ')'
better_assert( a == 1 );
^
prog.cc:22:192: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
^
prog.cc:28:5: note: to match this '('
prog.cc:22:92: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
^
prog.cc:29:5: error: expected ')'
better_assert( a == b, "Error: expected a == b, but a = ", a, " and b = ", b );
^
prog.cc:22:192: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
^
prog.cc:29:5: note: to match this '('
prog.cc:22:92: note: expanded from macro 'better_assert'
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : xxxxxxxx::print_assertion(std::cerr, "[Assertion Failure]: '", #EXPRESSION, "' in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
^
2 errors generated.
Эта проблема, вероятно, связана только с gccмакросы __VA_OPT__
и __VA_ARGS__
.У меня вопрос, есть ли способ сделать этот better_assert
макрос переносимым с clang?
Онлайн код для вашей справки: https://wandbox.org/permlink/ggcafJ5zbGrg5ZTx
Я заметил предложение __VA_OPT__
в с ++ 20.Может быть, это лучший способ решить эту проблему?