Home > Software design >  C avoid passing void expression to function
C avoid passing void expression to function

Time:02-15

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.

  • Related