一般情况下,码代码时候都会有对函数进行连续的调用,并对每次调用结果做判断。如下述示例:
我们定义函数 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的值等于最终失败那个函数的返回值,如果返回值定义的合理,那么很快就能知道,函数在哪里失败,以及失败的错误码!