函数模板限定数据类型 和 类模板限定数据类型 的方法

来源:互联网 发布:mysql备份脚本 编辑:程序博客网 时间:2024/06/14 15:10

函数模板非常有用,特别实在对不同类型的数据进行统一处理的时候,比如说比较两个数的大小,

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 >::typefun(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>::Typetest1(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);}