C++:return void 函数的 return 值来自 void 函数

C++: return the return value of a void function from a void function

我有几个 void 函数(我们称它们为 foo 和 bar),它们共享相同的 void 函数清理,好吧,如果它们搞砸了,就会在它们之后清理:

#include <iostream>

void cleanup() { std::cout << "doing cleanup" << std::endl; }

void foo(int & i) {
    if(i == 0) { return cleanup(); }
    --i;
    if(i == 0) { return cleanup(); }
    ++i;
}

void bar(int & i) {
    if(i == 0) { return cleanup(); }
    ++i;
    if(i == 0) { return cleanup(); }
    --i;
}

int main() {
    int i = 0;
    foo(i);
    bar(i);
    return 0;
}

cpp.sh愉快的编译运行代码

感谢 the answer to this question 我知道我可以 return 类型为 void 的对象。但我不知道它是否适用于 returning void return 值。

你怎么看,代码是否符合标准?

您是否愿意 return 虚拟整数来提高代码的可读性?还是无用的 return 值会使代码更难阅读?

编辑:我觉得我需要添加一些说明,例如为什么'cleanup(); return;' 不是解决方案。实际代码比示例更复杂,并且根据我离开函数的位置,在 cleanup() 调用之后会发生一些其他事情。 'return cleanup();' 只是一种方便的方式,在我 can/have 立即离开的情况下,不将所有内容放在条件句中。

这对于完美转发很有用。假设您有一个类型为 (template-parameter) 的仿函数,因此 return 类型可能是任何类型。这种对 return 类型 void 值的权限允许您调用仿函数并将其 return 值公开给您的调用者,而无需为没有 [=26] 的情况编写单独的代码=]值。

template<typename Functor, typename... Args>
auto forward(Functor what_to_call, Args... args) -> decltype(what_to_call(std::forward<Args>(args)...))
{
    return what_to_call(std::forward<Args>(args)...);
}

这已经很混乱了,但如果不是因为能够使用 return 关键字传播 void return 类型,你需要两个由 enable_if 控制的变体。

template<typename Functor, typename... Args>
auto forward(Functor what_to_call, Args... args) -> enable_if<is_same_type<decltype(what_to_call(std::forward<Args>(args)...)), void>::value, void>::type
{
    what_to_call(std::forward<Args>(args)...);
    return;
}

template<typename Functor, typename... Args>
auto forward(Functor what_to_call, Args... args) -> enable_if<!is_same_type<decltype(what_to_call(std::forward<Args>(args)...)), void>::value, decltype(what_to_call(std::forward<Args>(args)...))>::type
{
    return what_to_call(std::forward<Args>(args)...);
}

所以,return function_returning_void();是为特殊情况设计的,它很有用。不要觉得你必须 return 类型 void 或任何其他类型的虚拟对象只是因为它是可能的。例如,不要做 return void();return -1;,只要 return; 就可以。

What do you think, does the code comply with the standard?

是的,确实如此。在函数 returning void 中,如果表达式的类型是 void,则可以在 return 语句中使用表达式。如果它是对函数的调用也是 returns void.

And would you rather return dummy integers to make the code more readable? Or would the useless return values make the code harder to read?

我认为虚拟整数不会使代码更具可读性。程序员期望 return 值是有意义的。

我认为更具可读性的是将函数调用和 return 拆分为单独的语句:

cleanup();
return;

虽然我承认,这完全是见仁见智的事情。

来自n4582

6.6.3 return 语句 [stmt.return]

第 2 段

The expr-or-braced-init-list of a return statement is called its operand. A return statement with no operand shall be used only in a function whose return type is cv void, a constructor (12.1), or a destructor (12.4). A return statement with an operand of type void shall be used only in a function whose return type is cv void. A return statement with any other operand shall be used only in a function whose return type is not cv void; the return statement initializes the object or reference to be returned by copy-initialization (8.5) from the operand.

问题:

But I don't know if it applies to returning void return values.

是的,它对 return 来自 return void 函数的 void 表达式完全有效。这在模板代码中变得非常方便,因此您不必使用特殊情况的 void 函数。

What do you think, does the code comply with the standard?

绝对是。

And would you rather return dummy integers to make the code more readable? Or would the useless return values make the code harder to read?

这完全取决于您和您的审美。它是否使代码看起来更易读(或者您是否有需要遵循的编码指南)。就我个人而言,我不会 return 虚拟值(因为用户可能希望从中获得一些含义)。