c ++相同的函数检查一遍又一遍地返回

时间:2018-04-12 16:11:44

标签: c++ coding-style

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在瀑布方式上执行多个函数。每个函数都返回result。我应该确保result成功继续下一步。

这个if条件在代码上出现多次,这使得跟踪和阅读变得更加困难。

有没有办法彻底摆脱这种状况?

我正在考虑创建一个函数指针数组并在其上循环以仅检查代码一次,但由于函数参数的数量不同,我无法实现它。

2 个答案:

答案 0 :(得分:2)

这看起来很像错误处理("如果我得到非零错误代码,停止并返回该代码")。如果这些错误是例外的,那么在func1等内部使用异常处理可能是有意义的 - 如果它们返回非零错误代码,则它们会抛出一个预期。然后可以在最合适的位置(可能是多个函数调用)捕获此异常,从而避免在整个调用层次结构中进行错误处理。

如果错误不是例外,事情会变得复杂。如果您可以将所有函数调用打包到某种容器中,则可以迭代该容器。这里的问题是找到函数的通用类型 或者,可变参数模板可以完成这项工作:

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); }
    );
}

https://godbolt.org/g/wihtCj

这包装了lambdas中的所有函数调用,然后使用可变参数模板递归一个接一个地调用它们,只要每个结果为0.相对于另一个答案中显示的std::function方法的优势在于编译器更容易查看和优化。它的使用更简洁,更可重复使用。

答案 1 :(得分:1)

我可以想到以下几种简化代码的方法。

选项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 s

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

这是一种混合方法,它使用辅助函数中的条件表达式和main函数中的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;
}