从宏传递到函数时避免传递 void 表达式

jfo*_*erg 2 c++ metaprogramming

我想编写一个调试宏,在出现错误时打印调用的函数的名称。问题是有些函数返回值,我想从宏返回任何值。

\n

这是我的尝试:

\n
#define check(expr) _check_expr(#expr, expr)\n\nextern bool check_for_error();\n\ntemplate <typename T> inline T _check_expr(const char *str, T value)\n{\n    if (check_for_error()) {\n        fprintf(stderr, "Failure: %s\\n", str);\n    }\n\n    return value;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我遇到的问题是,有时T = void编译器不会让我将类型表达式传递void给函数:

\n
../src/render.cc: In constructor \xe2\x80\x98render::impl::impl()\xe2\x80\x99:\n../src/render.cc:34:20: error: invalid use of void expression\n   34 |     check(glDisable(GL_DEPTH_TEST));\n
Run Code Online (Sandbox Code Playgroud)\n

我无法重新定义在宏下调用的函数checkcheck_for_error函数,这些函数是我的程序外部的。此外,在计算表达式之后需要检查错误。

\n

C++中有没有好的方法来解决这个问题?

\n

类似于:“如果该表达式的 decltype 为 void,则生成此代码,否则生成该代码”。

\n

Dan*_*our 5

void 函数可以返回 void 表达式。这也适用于 lambda:

#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;
    }
}
Run Code Online (Sandbox Code Playgroud)

可能有更好的解决方案,但这可行。此外,这至少需要当前形式的 C++17,但可能可以向后移植到 C++14 甚至 C++11。

https://wandbox.org/permlink/YHdoyKL0FIoJUiQb查看代码。