My command uses return codes and a string reference argument instead of exceptions to detect an error in the execution of a function.
We have some invariant checking that looks like this:
bool format(std::string &error, ...)
{
// call sprintf on "error" string with all passed arguments
return false;
}
bool func(std::string &error)
{
// .......................
if (!some_expression)
return format(error, /*some undefined number of args*/);
// .......................
}
I want to write a macro, that will perform this logic in one line like this:
REQUIRE(expr, functor, "test string");
REQUIRE(expr, functor, "number=%lld", 1ll);
REQUIRE(expr, functor, "number_1=%lld, number_2=%f", 1ll, 2.0);
When REQUIRE macro will be this:
#define REQUIRE(expression, functor, format, ...) \
{ \
if (!expression) \
return functor(format, __VA_ARGS__) \
}
But this solution doesn't work, when i pass only format string without any arguments (first case in example). I tryed all solutions from this question: Overloading Macro on Number of Arguments, but all of them requires writing overloading on all agrs count.
Here is my non-working code code for now:
#define REQUIRE_1(expression, functor, format) \
{ \
if (!expression) \
return functor(format); \
}
#define REQUIRE_2(expression, functor, format, ...) \
{ \
if (!expression) \
return functor(format, __VA_ARGS__) \
}
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define REQUIRE(...) GET_MACRO(__VA_ARGS__, REQUIRE_1, REQUIRE_2)(__VA_ARGS__)
bool functor(const char *format, ...)
{
// Here is passing args to something like printf
return false;
}
bool format(std::string &error, ...)
{
// call sprintf on "error" string with all passed arguments
return false;
}
bool func(std::string &error)
{
// .......................
if (!some_expression)
return format(error, /*some undefined number of args*/);
// .......................
}
int main()
{
REQUIRE(true, func, "test string");
REQUIRE(true, func, "number=%lld", 1ll);
REQUIRE(true, func, "number_1=%lld, number_2=%f", 1ll, 2.0);
// Samples for [5,6,7..infinite] arguments
}
How can i achieve needed behaviour?
CodePudding user response:
C 20 made it possible to call #define F(x, y, ...)
as F(1, 2)
, without the comma after the last argument.
If C 20 is available, the only change you need to do is to replace , __VA_ARGS__
with __VA_OPT__(,) __VA_ARGS__
to the remove the comma if no extra arguments are passed.
Otherwise, just combine format
and ...
parameters into a single ...
parameter.