One of the things we did in XCTest that turned out to be extremely useful in practice was to allow every one of our assertion macros to take a format string and subsequent arguments through the use of variadic macros. That eliminated the need for distinct macros like ck_assert() versus ck_assert_msg().
Making this optional based on compiler support for variadic macros would, of course, mean that the assertion macros will take up even more space than they already do. That could be alleviated by breaking them out into a separate check_macros.h header, and maybe even a check_macros_impl.h header so the developer-facing macros can defer to more verbose primitive macros that only maintainers ever need to really care about.
The main trick that enables this is the preprocessor-level behavior of C string tokens. ck_assert() could be implemented like this
#define ck_assert(expr, ...) \
(expr) ? \
_mark_point(__FILE__, __LINE__) : \
_ck_assert_failed(__FILE__, __LINE__, "Assertion '"#expr"' failed" , "" __VA_ARGS__)
and it would obviate the need for ck_assert_msg().
The use of "" __VA_ARGS__ without an intermediate ## means that the first optional argument must be a string literal (which is what you generally want for a format string), and that if there are no arguments just an empty string will be passed.
One of the things we did in XCTest that turned out to be extremely useful in practice was to allow every one of our assertion macros to take a format string and subsequent arguments through the use of variadic macros. That eliminated the need for distinct macros like
ck_assert()versusck_assert_msg().Making this optional based on compiler support for variadic macros would, of course, mean that the assertion macros will take up even more space than they already do. That could be alleviated by breaking them out into a separate
check_macros.hheader, and maybe even acheck_macros_impl.hheader so the developer-facing macros can defer to more verbose primitive macros that only maintainers ever need to really care about.The main trick that enables this is the preprocessor-level behavior of C string tokens.
ck_assert()could be implemented like thisand it would obviate the need for
ck_assert_msg().The use of
"" __VA_ARGS__without an intermediate##means that the first optional argument must be a string literal (which is what you generally want for a format string), and that if there are no arguments just an empty string will be passed.