问题描述 #
现有一个函数模板和模板类定义在foo.h头文件中,
函数模板定义如下:
template<typename T>
T max(T a, T b) {
T maxVal;
if (a > b) {
maxVal = a;
} else {
maxVal = b;
}
return maxVal;
}
模板类定义如下:
template<typename T>
class MaxComputer {
public:
T max(T a, T b) {
T maxVal;
if (a > b) {
maxVal = a;
} else {
maxVal = b;
}
return maxVal;
}
};
在foo.cpp文件中,对函数模板有int类型的调用,如下
int foo(int i) {
if (max(i, 10) == i) {
return i;
}
return 0;
}
对模板类有float类型的调用,如下:
float goo(float f) {
MaxComputer<float> mcf;
if (mcf.max(f, 10.0) == f) {
return f;
}
return 0;
}
现在希望为模板函数/模板类中的方法来生成桩函数,控制测试执行路径,增加覆盖率,但是执行“Collect Stub Information”后,在桩函数面板中没有找到模板函数“maxInFun”和模板类的函数“maxInClass”,无法为其打桩。
问题原因 #
函数模板只是声明了一个函数的描述即模板,不是一个可以直接执行的函数,只有根据实际情况用实参的数据类型代替类型参数标识符之后,才能产生真正的函数。所以只有实际调用时,如max
template <>
int maxInFun<int>(int a,int b){
int maxVal;
if (a > b) {
maxVal= a;
} else {
maxVal= b;
}
return maxVal;
}
如果是模板类,同样的,中间代码如下:
template<>
class MaxComputer <int>{
public:
int maxInClass(int a, int b) {
int maxVal;
if (a > b) {
maxVal = a;
} else {
maxVal = b;
}
return maxVal;
}
};
这种转换是隐式的,所以收集不到模板函数/模板类的相关信息。
解决办法 #
方法一 #
C++提供了一种显示转换的方式,就是具化(显示实例化)。
Step1:若函数模板/类没有具化(显示实例化),则编译时在预处理文件中根本找不到此函数。所以先将其具化(显示实例化),如下
#ifdef PARASOFT_CPPTEST
template <>
int maxInFun<int>(int a,int b);//用int类型显示实例化
template<>
class MaxComputer<float> {
public:
float maxInClass(float a, float b);//用float类型显示实例化
};
template <>
double maxInFun<double>(double a,double b);//用double类型显示实例化
#endif
显式实例化只需声明,不需要重新定义。编译器会根据模板实现实例声明和实例定义。
Step 2:
再次运行“Collect Stub Information”后,在控制台下有如下信息:
并在桩函数面板中,可以看到:
现在就可以为模板函数/模板类的函数生成桩函数了。
方法二 #
有时候模板函数/类比较复杂,所以可能不能为函数正确地具化,这里有另外的方法。
因为函数执行的时候肯定会执行到模板函数/类中,所以可以在模板函数/类中修改代码,达到“打桩”的目的,代码如下:
#ifdef PARASOFT_CPPTEST
#include"cpptest.h"
#endif
template<typename T>
T maxInFun(T a, T b) {
T maxVal;
#ifdef PARASOFT_CPPTEST
if(CppTest_IsCurrentTestCase("test_foo_1"))
{
return 0;
}
#else
if (a > b) {
maxVal = a;
} else {
maxVal = b;
}
return maxVal;
#endif
}