函数链式调用机制(非回调)

一般情况下,码代码时候都会有对函数进行连续的调用,并对每次调用结果做判断。如下述示例:
我们定义函数 func_impl(),函数内部调用 func_internal_1(),func_internal_2(),func_internal_3()。这三个函数执行成功的返回值均是0,失败则有不同的错误码。
那么按照一般的写作方式,可以写成如下形式:

void func_impl()
{
    int ret;

    ret = func_internal_1();
    if (ret)
    {
        std::cout<< "some error"<<std::endl;
        return ret;
    }

    ret = func_internal_2();
    if (ret)
    {
        std::cout<< "some error"<<std::endl;
        return ret;
    }

    ret = func_internal_3();
    if (ret)
    {
        std::cout<< "some error"<<std::endl;
        return ret;
    }
    return 0;
}

如上,功能没问题,但是中间判断返回值太罗嗦。很大段的重复,功能无关的代码!!!

反思: 如果能把错误判断,精简下,代码量会下降很多!

经过一番思考,采取如下形式:


void func_impl()
{
    int ret;

    ret = func_internal_1() ||
          func_internal_2() ||
          func_internal_3();
    if (ret)
        std::cout<< "some error"<<std::endl;
    return ret;
}

如上代码量确实下降了许多,而且利用|| 的性质,func_internal_1,func_internal_2,func_internal_3,任意一个执行失败,都会直接返回。确实符合预期,但是不足的是,ret的值将只会是 bool 类型,只有0和1 两个值。那么最终我们只知道函数成功与否,如果没有更详细的log,就无法判断 func_internal_1,func_internal_2,func_internal_3,到底哪个函数失败了!!!

再次反思,改成如下形式:

// define anyone template function
template <typename T>
auto anyone(T arg) -> decltype(arg)
{
    return arg;
}

template <typename T, typename... Args>
auto anyone(T arg, Args... args) -> decltype(arg)
{
    return arg ? arg : anyone(args...);
}

void func_impl()
{
    int ret;

    ret = anyone(func_internal_1(),
                 func_internal_2(),
                 func_internal_3());
    if (ret)
        std::cout<< "some error"<<std::endl;
    return ret;
}

ok! 至此利用模板推到的特性,我们可以实现,ret的值等于最终失败那个函数的返回值,如果返回值定义的合理,那么很快就能知道,函数在哪里失败,以及失败的错误码!

猜你喜欢

转载自www.cnblogs.com/sinpo828/p/12656793.html
今日推荐