假设从设备上读取一个配置文件,这个文件有特定的格式,即文件由若干个段落构成,每个段落有一个标志字段ID,一个记录长度的字段LEN,以及若干数据字段。

以下是一个例子,这个ID为0x70的段落记录了设备运行状况信息,包括设备的温度以及风扇转速:

另一个ID为0x80的段落记录了设备的告警信息:

如果用C++的struct来描述上面的段落,分别起名为StatusSection和WarningSection:

从设备中读取出的信息是以一段字节序列,我们需要要写一个函数把StatusSection和WarningSection从字节序列取出,假设这个函数取名叫extractSection,我们希望这样使用它:

为了让extractSection适应不同的段落,这里使用到的是C++11引入的新特性:Variadic Templates,所以extractSection是一个带可变长参数的函数模板,实现如下:

被调用的子函数extractAllFields递归遍历所有的模板参数,将段落内容从字节序列中提取出来。

首先我们要申明一个可变长参数为零的extractAllFields作为递归终止条件:

然后是extractAllFields的递归函数主体:

extractAllFields调用extractField从字节序列中提取出段落内容。extractField可以提取四种长度的数值,从一个字节到四个字节:

总结:

C++11引入了很多新的特性,使C++语言在模板语法方面得到提升。上面的代码使用到的C++11的新特性包括:

  • Variadic Templates
  • static (compile-time) assertions
  • constant expressions

虽然C++11的新特性很玄,但为了使用新特性而使用新特性往往会走火入魔,写这篇糟糕的文章是为了提醒我自己,代码简单通俗易懂好维护才是最重要的。

cppreference.com上有详细的关于可变长参数的使用介绍,请参考 parameter_pack