C++11新特性(68)- 可变参数模板(variadic template)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/craftsman1970/article/details/82354078

可变参数函数

C语言中,可变参数函数可以说是一个比较神奇的存在。例如最常用的printf函数,它的原型如下:

它的第一个参数是const char*类型的format,后面参数的类型和名称都没有定义,只有三个点。

虽然从C语言编译的角度来讲,在这个位置程序员可以写任意个数,任意类型的参数,实际上printf函数根据format指定的格式字符串来使用后面指定的 实参值,个数少了或者类型错误常常会导致错误。可变参数的个数,类型要通过前面的参数来传递,这算是可变参数的第一个难点。

由于可变参数函数的原型中只是说参数可变,但是并没有指定这些可变的参数保存在哪里,需要另外的方法来生成参数列表。例如下面的示例代码:

首先定义参数列表,然后通过va_start取得变量列表的内容,使用后再使用va_end释放变量列表。这个必须的步骤是可变参数函数的第二个难点。

可变参数模板声明

C++11增加了可变参数模板,可以接受可变数目,类型的参数。我们通过开发中常用的输出调试信息的例子介绍绍可变参数模板的使用方法。首先是声明可变参数模板。

在模板参数定义的部分,通过typename...定义可变模板参数。三个点的含义和C语言中的可变参数定义类似,不同的是后面接着指定了可变参数列表的名称Args。

在参数定义的部分,使用可变模板参数定义的Args以相同的格式定义函数的可变参数列表。

这个参数列表可以在模板函数的实现中直接使用,这样在定义可变参数模板时就解决了可变参数函数的第二个难点。

可变参数模板的实现

可变参数模板的实现通常需要一些小技巧:递归和重载。还是先看代码。

代码中定义了两个重载的writeLog函数,一个只接受类型为T的参数t,另一个除了t之外,还接受可变参数rest。当使用一个参数调用writeLog的时候,实际调用上面的函数;当使用多个参数调用writeLog的时候调用下面的writeLog。

下面的writeLog首先使用第一个参数t调用上面的writeLog之后,使用rest递归调用writeLog(严格讲是rest中有多于一个参数的 时候)。从调用者来看,每次处理一个参数之后,使用其余的参数再次调用writeLog,直到最后调用一个参数的writeLog。

下面是使用writeLog的示例代码:

可以任意组合参数的类型和个数,而且不需要另外提供任何信息。这样就有效地解决了可变参数函数的第一个难点。

更近一步

本例中一个参数的writeLog非常简单,只是简单的使用cout进行输出,如果有特殊的需求,可以继续重载这个函数。例如log输出中经常需要的时间信息,就可以这样实现:

使用方法更加简单:

输出结果

字体一如既往的丑,但是内容可以说足够神奇!

作者观点

虽然理解起来困难一些,但是却是可以写出很神奇的代码,值得研究。

觉得本文有帮助?请分享给更多人。

阅读更多更新文章,请扫描下面二维码,关注微信公众号【面向对象思考】

猜你喜欢

转载自blog.csdn.net/craftsman1970/article/details/82354078