函数模板非常有用,特别实在对不同类型的数据进行统一处理的时候,比如说比较两个数的大小,
template<typename T>
bool compara(T& a,T& b)
{
return a<b;
}
但是有时候有特殊需求,比如说之前我做的一个项目,需要能够处理以glm中vec2,和vec3为数据类型的数据,进行同样的操作,但是又不能让其他类型的数据能够访问到该函数模板。此时就需要一种限定数据类型(指定模板处理那几个数据类型)的方法。这里有两种方法可以解决函数模板数据类型限定。
第一种
template<typename T>
typename std::enable_if < std::is_same<glm::dvec3, T>::value
|| std::is_same<glm::dvec2, T>::value, void >::type
fun(vector<T>& id)
{
cout << "--" << id[1][0] << endl;
cout << "--" << id[1][1] << endl;
cout << "--" << id[1][2] << endl;
}
第二种
template <typename T> struct Checker;
template <> struct Checker<glm::dvec3> { typedef glm::dvec3 Type; };
template <> struct Checker<glm::dvec2> { typedef glm::dvec2 Type; };
template <typename T>
typename Checker<T>::Type
test1(vector<T>& var)
{
cout << "--" << var[1][0] << endl;
cout << "--" << var[1][1] << endl;
return var[1];
}
上面的两种方法,都是当T为dvec3和dvec2时候,程序才能正常编译。
此种方法就可以实现限定访问模板函数的数据类型。
此外,如果是类模板呢?类模板如何限定数据类型?
如果想实现这个功能,那么需用到静态assert。
静态assert可以解决模板的状态检测,使用新的关键字static_assert。
声明采取一下的形式:
static_assert(constant-expression, error-message);
这里有一些使用static_assert的例子:
static_assert(3.14 < GREEKPI && GREEKPI <3.15, "GREEKPI is inaccuratel");
template<class T>
struct Check
{
static_assert(sizeof(int)<= sizeof(T), "T is not big enough!");
}
当常数表达式为false时,编译器就会产生响应的错误新型。第一个例子是预处理器指令#error的替代方案,第二个例子会在每个模板类别Check生成时检查assertion。
静态assertion在模板之外也是相当有用的。例如,某个算法的实现依赖long long类别的大小比int 还大,这是标准不保证的,这种假设在大多数的系统以及编译器上是有效的,但不是全部。
这里给出一个我测试的例子,帮助大家理解
#include <vector>
#include <iostream>
//定义一个模板类,但是模板类只能处理int 和 float 类型的数据,否则编译不通过
//将会报T type is not the specified DataType including int and float错误提示
template <typename T>
class Box
{
static_assert( sizeof(int) == sizeof(T) || sizeof(float) == sizeof(T),
"T type is not the specified DataType including int and float");
public:
Box();
~ Box();
void comprr(T& arr);;
private:
T aa;
};
template <typename T>
void Box<T>::comprr(T& arr)
{
std::cout << "******" << arr << std::endl;
}
template <typename T>
Box<T>::~Box()
{}
template <typename T>
Box<T>::Box()
{}
int main()
{
int aa = 5;
float ab = 4.5;
double ac = 4.4;
//编译可以通过,类模板使用int数据类型,允许
Box<int>* box = new Box<int>();
box->comprr(aa);
//编译可以通过,类模板使用float数据类型,允许
Box<float>* box = new Box<float>();
box->comprr(ab);
//编译不通过,报错,因为类模板不允许使用double类型
//Box<double>* box = new Box<double>();
//box->comprr(ac);
}