基于模板元编程的量纲检测方法
sprey方法中,量纲是用一个长度为7的向量表示的,每个分量对应一个SI标准量纲。TADA方法中也采用了这种方式。为了简化阐述,本文只讨论长度、重量、时间这三种量纲,其SI单位分别为米、千克和秒(TADA方法可直接推广到其他各种量纲)。由于TMP程序的特殊性,它并没有数组或向量的支持,也不能使用浮点数据(使用浮点数表示量纲也会带来不精确性),量纲在TMP程序中的表示形式有所不同:用u11,u12,u21,u22,u31,u32之类的整型量分别表示
,
并辅以ratio表示同量纲、不同单位之间的比值,如分钟和秒的比值为60。
TADA方法可静态地建立如下常用单位:
模板元程序在计算公式的时候需要推导出新的量纲,例如在计算
的时候,编译器应该能根据等号右边的公式计算出它的量纲,并与e的量纲进行比较判别。TADA方法的量纲是用分数形式表示的,在每次量纲计算之后都需要进行分数的约分处理,才能进行相等性判断,因而TADA方法可用如下的方式处理新生成单位,如下所示。
2.2 单位和量纲的计算
由于量纲都是用分数表示的,因而其计算会稍有麻烦。下面定义TADA方法中量纲分数的加、减、乘、除和等价测试运算。
(1)分数的加法运算,如下所示。
(2)分数的减法运算。TADA方法通过加法实现减法计算,如下所示。
语义:分数相减并约分,即:
(3)单位相乘。分别将3个量纲分数相加,然后使用BuildUnit生成新单位。
语义:单位Ua与单位Ub相乘后的新单位。
(4)单位相除。与乘法处理方式相似。
语义:若单位ua与单位Ub等价则不产生任何效果,否则产生编译期错误。
2.3 单位和量纲标注的原理和语法
与Osprey等方法类似,TADA方法也在待检测源程序进行单位标注,以使得检测器能够知道每个变量的单位。由于经过单位标注的待检测程序仍然是合法的可编译的程序,所以标注信息必须由语言自身已有的语法要素构成;标注信息还不能影响被标注变量的任何计算特性及使用方式,只有满足这两点要求的标注方式才能使标注工作量最小化。此外,已标注变量应该禁止从未标注变量进行各种隐含的类型转换,这样严格的限制才能有效进行单位量纲的匹配检测。对于C++语言来说,可以采用模板类的方式实现。
标注实质上是把语言原始的数据类型替换成TADA方法预定义的模板类,而模板类实现了各种运算符号的重载,同时禁止了任何隐含的类型转换,使得量纲标注既满足语法要素的要求,又满足计算兼容性的要求和禁止隐含转换的要求。TADA方法中标注的实现如下所示。
2.4 定义单位量纲
量纲检测系统应该预定义常用单位量纲,以方便应用开发人员使用。TADA方法采用如下方式定义单位量纲:
2.5 数学运算函数的量纲包装
对于指数、对数、三角函数等已有的数学运算函数,其参数与返回值都是没有单位量纲的,不能直接用于有量纲的公式计算。针对这个问题,.TADA方法提供了这些函数的量纲包装,以sqrt和sin为例如下:
2.6 辅助工具
TADA方法还提供了一些辅助工具,用于将量纲变量以适合阅读的方式显示出来,例如:
可以得到这样的输出结果:0.2米/秒2
2.7 分析和评估
在TADA方法的基础上,实现了面向C/C++程序的量纲检测系统(TADA系统),并对TADA系统的检测能力进行了分析和评估。
首先采用TADA系统来检测下面的样例程序。
在TADA系统中,Visual Studio 2003编译该程序会出现类似如下的错误信息,错误信息的第3行就表明了unit.epp的第9行有错误。
在检测能力方面,采用文献的样例程序对TA-DA系统和Osprey系统的量纲检测能力进行了对比评估。在文献中,Osprey共找到了3个错误,其中前2个是单位误用错误,第3个是单位转换比例因子错误。TADA系统也完全找到了前2个错误,而第3个错误在标注时被避免掉了,因为该单位系统包含了量纲之间的比例因子,能够进行自动的单位转换。
在性能和可扩展性方面,TADA系统能够更有效地实现对c/c++程序的量纲检测。Osprey系统引入了具有较高计算复杂度的线性方程组求解步骤,需要很大的计算和时间开销来解线性解方程组。TADA系统基于模板元编程技术,只需要利用语言自身的语法能力,靠编译器进行单位量纲检查,没有带来太多额外的复杂计算。并且TADA系统不会带来任何程序的运行时开销。因此TADA系统可适用于各种规模的C/C++程序,具有更好的性能和可扩展性。
在易用性方面,TADA系统的标注负担与Osprey系统相当。由于TADA系统利用C++编译器的功能进行错误检测,而C++编译器遇到模板错误时的错误信息却不很直观,错误报告的可读性较弱,但仍可以快速定位到错误点。
3 结 语
这里提出一种新颖的基于模板元编程的
- 一种基于模板元编程的量纲检测方法(07-14)