c++ - 在没有 goto 和提前返回的情况下在 C++ 中执行多个相关错误检查的优雅方法?

标签 c++ error-handling goto

关闭。这个问题是opinion-based .它目前不接受答案。












想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它.

7年前关闭。




Improve this question




假设我想连续调用四个函数,它们对我的某个对象进行操作。如果其中任何一个失败,我想返回 FAILURE不调用其他人,我想返回SUCCESS如果所有这些都成功完成。

通常,我会做这样的事情:

if(function_zero(&myMutableObject) == SUCCESS)
{
    return FAILURE;
}
if(function_one(&myMutableObject) == SUCCESS)
{
    return FAILURE;
}
if(function_two(&myMutableObject) == SUCCESS)
{
    return FAILURE;
}
if(function_three(&myMutableObject) == SUCCESS)
{
    return FAILURE;
}

return SUCCESS;

或者,如果我需要进行一些清理:
if(function_zero(&myMutableObject) == SUCCESS)
{
    status = FAILURE;
    goto cleanup;
}
if(function_one(&myMutableObject) == SUCCESS)
{
    status = FAILURE;
    goto cleanup;
}
if(function_two(&myMutableObject) == SUCCESS)
{
    status = FAILURE;
    goto cleanup;
}
if(function_three(&myMutableObject) == SUCCESS)
{
    status = FAILURE;
    goto cleanup;
}

cleanup:
// necessary cleanup here
return status;

但是,我正在从事的项目有一些限制:
  • 没有 goto , 永远
  • 不提前返回(每个函数返回一次)
  • 行长限制
  • (编辑)没有异常(exception)。
  • (编辑)没有模板。

  • 这导致我是这样的:
    if(function_zero(&myMutableObject) == SUCCESS)
    {
        if(function_one(&myMutableObject) == SUCCESS)
        {
            if(function_two(&myMutableObject) == SUCCESS)
            {
                status = function_three(&myMutableObject);
            }
            else
            {
                status = FAILURE;
            }
        }
        else
        {
            status = FAILURE;
        }
    }
    else
    {
        status = FAILURE;
    }
    
    return status;
    

    不幸的是,这经常使我违反行长限制。

    我的问题是:有没有更简单的方法来写这个?

    注意事项和限制:
  • 我必须在此处隐含的代码块中实现此逻辑。我无法创建新功能、重构或更改整体架构。
  • (编辑)实际上,这些功能具有非常不同的签名。
  • 最佳答案

    使用异常(exception)和 RAII。这些实际上是他们被发明来解决的问题。异常(exception)更多的是系统范围的功能,而不是您可以在本地应用的东西。

    对于清理 block ,RAII 正是您需要的功能。

    对于成功/失败,我们可以使用 lambdas 和 variadics 将它们隐式链接在一起。

    现在我们可以简单地将它们写为列表中的 lambdas。

    status f() {
        struct nested {
            static template<typename F> status_t Check(F f) {
                return f();
            }
            static template<typename F, typename... Chain> status_t Check(F f, Chain... chain) {
                auto status = f();
                return status != failure ? Check(chain...) : status;
            }
        };
        return nested::Check( 
            [] { return function_zero(&myMutableObject); },
            [] { return function_one(&myMutableObject); },
            [] { return function_two(&myMutableObject); },
            [] { return function_three(&myMutableObject); },
        );
    }
    

    如果您需要捕获返回值,这会变得稍微有点问题,但由于它似乎总是一个没有参数的错误代码,如果您只是在 f() 中声明接收变量应该没问题。 , 那么所有 future 的 lambdas 都可以引用它。它也不要求每个函数都具有相同的签名,或者分配各种数据结构。

    关于c++ - 在没有 goto 和提前返回的情况下在 C++ 中执行多个相关错误检查的优雅方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24832995/

    相关文章:

    c++ - 无法将 Qt 链接到 Xcode

    c++ - Mac/IOS 是否使用与 Linux 内核相同的 sys/socket.h?

    c - 转到标签后的变量声明

    php - 引用 - 这个错误在 PHP 中意味着什么?

    c++ - 跳过变量初始化格式不正确还是会导致不确定的行为?

    c++ - 没有goto跳入和跳出循环的更好方法?

    c++ - 算法循环组合

    c++ - 如何退出 C++ 中的 void 函数?

    Scala 解释器 : anyway to get the line of a compile error?

    c# - 获取堆栈跟踪中的参数值