C++ 我应该如何处理状态机中的异常?

C++ 我应该如何处理状态机中的异常?,c++,exception-handling,try-catch,noexcept,C++,Exception Handling,Try Catch,Noexcept,我从我的状态机中调用了很多外部函数——要么显式地像sendMessage(…)要么隐式地像a=b。到目前为止,我一直在努力跟踪可以扔的东西,但随着数量的增加,需要一种更好的方法。丢失一个异常并允许它传播到状态机框架的代码中显然会造成很大的混乱 我看到了三个选择,但我希望有人能给我指出一个更好的选择: 在每个onetry、onExit和操作处放置一个try catch。由于它们有很多,而且非常简单,这几乎会使代码长度增加一倍,并降低可读性 制作大量函数noexcept。在函数被其他地方使用的情况下

我从我的状态机中调用了很多外部函数——要么显式地像
sendMessage(…)
要么隐式地像
a=b
。到目前为止,我一直在努力跟踪可以扔的东西,但随着数量的增加,需要一种更好的方法。丢失一个异常并允许它传播到状态机框架的代码中显然会造成很大的混乱

我看到了三个选择,但我希望有人能给我指出一个更好的选择:

  • 在每个
    onetry
    onExit
    操作处放置一个
    try catch
    。由于它们有很多,而且非常简单,这几乎会使代码长度增加一倍,并降低可读性

  • 制作大量函数
    noexcept
    。在函数被其他地方使用的情况下,或者在它可以合法抛出并且异常是唯一好的解决方案的情况下,这似乎是不可能的

  • 修改我调用的大多数函数,以使用alexandrescu的
    Expected
    作为返回类型。见:


  • 哪种选择最好?有更好的策略吗?

    与其将每个
    onEntry、onExit
    action
    包装在try-catch块中,更好的方法是实现onEntry、onExit和action的noexcept包装版本,这些版本只需调用
    onEntry,在try-catch块中执行onExit
    操作
    ,并处理抛出的任何异常

    在代码中,您只需调用包装器而不是实际的函数,使用异常处理对您有利,但避免重复try/catch逻辑

    void onExitWrapper(int arg1, int arg2) noexcept
    {
    try
    {
    onExit(arg1,arg2);
    }
    catch(/*whatever*/)
    {
    //handle exception
    }
    }
    
    如果不同函数的异常处理类似,您还可以创建特殊函数,该函数接收函数指针/lambda和输入参数,并使用try-catch中的输入参数调用函数指针引用的函数:

    template <class Arg1,class Arg2,class Ret> Ret exceptionHandler(Ret (funcPtr *)(Arg1,Arg2),Arg1 arg1,Arg2 arg2)
    {
        Ret output;
        try
        {
         output = funcPtr(arg1,arg2);
        }
        catch(/*whatever*/)
        {
        //handle exceptions
        }
        return output;
    }
    
    模板Ret异常处理程序(Ret(funcPtr*)(Arg1,Arg2),Arg1 Arg1,Arg2 Arg2)
    {
    Ret输出;
    尝试
    {
    输出=funcPtr(arg1,arg2);
    }
    捕获(/*任意*/)
    {
    //处理异常
    }
    返回输出;
    }
    
    异常处理程序应如何处理捕获的异常?我想它只是改变了状态。将异常视为无法处理的异常。并始终添加错误状态,这样就不必抛出错误。