c ++ 一遍又一遍地检查函数 return
c++ Same checking on function return over and over again
int cmd_x() {
int result;
result = func1(x, y);
if (result != 0) {
return result;
}
result = func2();
if (result != 0) {
return result;
}
result = func1(x, y, z, w);
if (result != 0) {
return result;
}
...
return result;
}
cmd_x
以瀑布方式执行多个函数。每个函数returnsresult
。我应该确保 result
成功才能继续下一步。
此 if
条件在代码中多次出现,这使得它更难理解和阅读。
有没有办法彻底摆脱这种情况?
我想创建一个函数指针数组并循环它以仅检查一次代码,但我无法实现它,因为函数参数的数量不同。
我可以想到以下方法来稍微简化您的代码。
选项 1:使用条件表达式
int cmd_x()
{
int x = 0, y = 0, z = 0, w = 0;
int result = func1(x, y);
result = (result != 0) ? result : func2();
result = (result != 0) ? result : func1(x, y, z, w);
// ...
result = (result != 0) ? result : funcN();
return result;
}
选项 2:使用 std::vector
个 std::function
int cmd_x()
{
int x = 0, y = 0, z = 0, w = 0;
std::vector<std::function<int()>> functionList =
{
// Let the lambda functions capture what they need
[x, y]() -> int { return func1(x, y); },
[] () -> int { return func2(); },
[x, y, z, w] () -> int { return func1(x, y, z, w); },
[] () -> int { return funcN(); }
};
for ( auto fn : functionList )
{
int result = fn();
if ( result != 0 )
{
return result;
}
}
return 0;
}
选项 3:使用辅助函数和 std::function
这是一种混合方法,在辅助函数中使用条件表达式,在主函数中使用 lambda 函数。
int cmd_helper(int r, std::function<int()> fn)
{
return ( r != 0 ) ? r : fn();
}
int cmd_x()
{
int x = 0, y = 0, z = 0, w = 0;
int result = 0;
result = cmd_helper(result, [x, y]() -> int { return func1(x, y); });
result = cmd_helper(result, [] () -> int { return func2(); });
result = cmd_helper(result, [x, y, z, w] () -> int { return func1(x, y, z, w); });
result = cmd_helper(result, [] () -> int { return funcN(); });
return result;
}
这看起来很像错误处理 ("if I get a nonzero error code, stop and return that code")。如果这些错误是异常的,那么在 func1
等中使用异常处理可能是有意义的 - 如果它们 return 一个非零错误代码,它们就会抛出一个期望。然后可以在最合适的位置(可能是几个函数调用)捕获此异常,从而避免在整个调用层次结构中进行错误处理。
如果错误不是异常的,事情就会变得复杂。如果您可以将所有函数调用打包到某种容器中,则可以迭代该容器。这里的问题是找到函数的通用类型。
或者,可变参数模板可以完成这项工作:
template<class Func, class... OtherFuncs>
int cmd_x_impl(Func&& func, OtherFuncs&&... otherFuncs)
{
int result = func();
if (result != 0)
return result;
cmd_x_impl(otherFuncs...);
}
template<class Func>
int cmd_x_impl(Func&& func)
{
return func();
}
int cmd_x() {
return cmd_x_impl(
[&]() { return func1(x, y); },
[&]() { return func2(); },
[&]() { return func1(x, y, z, w); }
);
}
这将所有函数调用包装在 lambda 中,然后使用可变参数模板递归一个接一个地调用它们,只要每个结果为 0。与另一个答案中显示的 std::function
方法相比的优势是这对于编译器来说更容易看穿和优化。在使用上也更加简洁,可重复使用。
int cmd_x() {
int result;
result = func1(x, y);
if (result != 0) {
return result;
}
result = func2();
if (result != 0) {
return result;
}
result = func1(x, y, z, w);
if (result != 0) {
return result;
}
...
return result;
}
cmd_x
以瀑布方式执行多个函数。每个函数returnsresult
。我应该确保 result
成功才能继续下一步。
此 if
条件在代码中多次出现,这使得它更难理解和阅读。
有没有办法彻底摆脱这种情况?
我想创建一个函数指针数组并循环它以仅检查一次代码,但我无法实现它,因为函数参数的数量不同。
我可以想到以下方法来稍微简化您的代码。
选项 1:使用条件表达式
int cmd_x()
{
int x = 0, y = 0, z = 0, w = 0;
int result = func1(x, y);
result = (result != 0) ? result : func2();
result = (result != 0) ? result : func1(x, y, z, w);
// ...
result = (result != 0) ? result : funcN();
return result;
}
选项 2:使用 std::vector
个 std::function
int cmd_x()
{
int x = 0, y = 0, z = 0, w = 0;
std::vector<std::function<int()>> functionList =
{
// Let the lambda functions capture what they need
[x, y]() -> int { return func1(x, y); },
[] () -> int { return func2(); },
[x, y, z, w] () -> int { return func1(x, y, z, w); },
[] () -> int { return funcN(); }
};
for ( auto fn : functionList )
{
int result = fn();
if ( result != 0 )
{
return result;
}
}
return 0;
}
选项 3:使用辅助函数和 std::function
这是一种混合方法,在辅助函数中使用条件表达式,在主函数中使用 lambda 函数。
int cmd_helper(int r, std::function<int()> fn)
{
return ( r != 0 ) ? r : fn();
}
int cmd_x()
{
int x = 0, y = 0, z = 0, w = 0;
int result = 0;
result = cmd_helper(result, [x, y]() -> int { return func1(x, y); });
result = cmd_helper(result, [] () -> int { return func2(); });
result = cmd_helper(result, [x, y, z, w] () -> int { return func1(x, y, z, w); });
result = cmd_helper(result, [] () -> int { return funcN(); });
return result;
}
这看起来很像错误处理 ("if I get a nonzero error code, stop and return that code")。如果这些错误是异常的,那么在 func1
等中使用异常处理可能是有意义的 - 如果它们 return 一个非零错误代码,它们就会抛出一个期望。然后可以在最合适的位置(可能是几个函数调用)捕获此异常,从而避免在整个调用层次结构中进行错误处理。
如果错误不是异常的,事情就会变得复杂。如果您可以将所有函数调用打包到某种容器中,则可以迭代该容器。这里的问题是找到函数的通用类型。
或者,可变参数模板可以完成这项工作:
template<class Func, class... OtherFuncs>
int cmd_x_impl(Func&& func, OtherFuncs&&... otherFuncs)
{
int result = func();
if (result != 0)
return result;
cmd_x_impl(otherFuncs...);
}
template<class Func>
int cmd_x_impl(Func&& func)
{
return func();
}
int cmd_x() {
return cmd_x_impl(
[&]() { return func1(x, y); },
[&]() { return func2(); },
[&]() { return func1(x, y, z, w); }
);
}
这将所有函数调用包装在 lambda 中,然后使用可变参数模板递归一个接一个地调用它们,只要每个结果为 0。与另一个答案中显示的 std::function
方法相比的优势是这对于编译器来说更容易看穿和优化。在使用上也更加简洁,可重复使用。