如果`f`具有非void返回类型,则返回`f`的结果 - 如何重构此模式?

Vit*_*meo 9 c++ refactoring metaprogramming return-type c++14

我有一个step(f)功能:

  1. 在调用之前执行一些代码f.

  2. 打电话f().

  3. 调用后执行一些代码f.

  4. 如果不返回返回f结果值.fvoid

step 由于上面提到的第四点,实现的一小段代码比我应该更困扰我:

template <typename TF>
auto step(TF&& f)
{   
    // Execute some actions before `f`. 
    do_something();

    using f_return_type = decltype(f());
    return static_if(std::is_same<f_return_type, void>{})
        .then([](auto&& xf) mutable
            {
                // Do not return anything if `xf` returns void.
                xf();

                // Execute some actions after `f`.
                do_something_after_f();
            })
        .else_([](auto&& xf) mutable
            {
                auto result = xf();

                // Execute some actions after `f`.
                do_something_after_f();

                return result;
            })(std::forward<TF>(f));
}
Run Code Online (Sandbox Code Playgroud)

(注意重复调用fdo_something_after_f.)

我必须使用某种条件编译时(模板特化或static_if如示例所示)根据f返回类型进行分支.

理想情况下,我希望这个编译:

template <typename TF>
auto step(TF&& f)
{   
    // Execute some actions before `f`. 
    do_something();

    decltype(auto) eventual_result = f();

    // Execute some actions after `f`.
    do_something_after_f();

    return result;
}
Run Code Online (Sandbox Code Playgroud)

但它没有,因为eventual_result可以void,这是一个不完整的类型.

有没有办法重构这段代码,以避免重复调用f()do_something_after_f()

Bri*_*ian 9

您可以do_something_after_f()通过将其放入局部变量的析构函数中来运行return语句.

struct Cleanup {
    ~Cleanup() { do_something_after_f(); }
} cleanup;
return f(); // it's legal to return a void expression in C++
Run Code Online (Sandbox Code Playgroud)

  • 非常聪明! (2认同)
  • @VittorioRomeo记得当`f`抛出时也会调用dtor,但在原始代码中,`do_something_after_f`将不会被调用.您可以使用`std :: uncaught_exception()`来捕获它 (2认同)