I want to write a debugging macro which prints the name of the function called when there is an error. The catch is that some functions return values, and I would like to return any value back from the macro.
This is my attempt:
#define check(expr) _check_expr(#expr, expr)
extern bool check_for_error();
template <typename T> inline T _check_expr(const char *str, T value)
{
if (check_for_error()) {
fprintf(stderr, "Failure: %s\n", str);
}
return value;
}
The problem I get here is that sometimes T = void and C will not let me pass an expression of void type to a function:
../src/render.cc: In constructor ‘render::impl::impl()’:
../src/render.cc:34:20: error: invalid use of void expression
34 | check(glDisable(GL_DEPTH_TEST));
I cannot redefine the functions to be called under the check macro, or the check_for_error function. They are external to my program. Also, checking for error needs to occur after evaluating the expression.
Is there a good way to solve this problem in C ?
Something like: "If decltype of this expression is void, then generate this code, otherwise generate that code".
CodePudding user response:
A void function can return a void expression: https://stackoverflow.com/a/2176229/1116364
This also applies to lambdas:
#define check(expr) _check_expr(#expr, [&] () { return expr; })
extern bool check_for_error();
template <typename Fn> inline auto _check_expr(const char *str, Fn fn)
{
auto check_ = [str]() {
if (check_for_error()) {
fprintf(stderr, "Failure: %s\n", str);
}};
if constexpr (std::is_same_v<std::invoke_result_t<Fn>, void>) {
fn();
check_();
} else {
auto v = fn();
check_();
return v;
}
}
There's probably a better solution but this works. Sorry for the formatting, am on mobile. Also this requires at least C 17 in the current form, but can probably be back ported to C 14 or even C 11
https://wandbox.org/permlink/YHdoyKL0FIoJUiQb
CodePudding user response:
You can not avoid pass void
if you always need the macro #define check(expr) _check_expr(#expr, expr)
. There is no overload or dispatch mechanism for macro.