模板的类型萃取

xiaoxiao2021-02-28  105

功能

  类型萃取,在STL中用到的比较多,用于判断一个变量是否为POD类型.

  简述来说可以用来判断出某个变量是内置类型还是自定义类型.

  通过类型萃取,萃取到变量类型,对不同变量进行不同处理,可以提升程序效率(下面有具体讲解).

应用场景

  比如我们实现顺序表,在对顺序表进行扩容时,就靠重新开辟内存、拷贝对象.

  拷贝对象时,就有两种情况:一种是类型,比如int char…;还有一种是自定义类型,Data类、String类.

  对于内置类型,我们可以通过memset,来进行赋值.(扩展,浅拷贝相关的类也可以通过memset赋值)

  而对于自定义类型,大多数深拷贝的对象来说,我们必须通过调用赋值语句来赋值.

  因此,我们通常在拷贝对象时,为了不出现错误,都用赋值语句来赋值.

  而我们如果有一种方法/机制可以判断POD类型或者非POD类型.

  对于POD类型用memset函数,对于非POD用赋值,这样就能提高程序的效率  


最大的功能

类型萃取的最大功能就是提高了程序的效率.例如下面的代码,就会出现错误。

template <class T> void Copy( T* dst, T* src,size_t size)//这里的size是数据个数 { memcpy(dst, src, sizeof(T)*size); }

如果T类型是int,char,float ...这些内置类型,使用memcpy()函数拷贝没有问题,并且使用memcpy()更快,比一个一个赋值赋值语句快很多,但是如果T类型是string这些自定义的类型(有自己的构造函数),使用memcpy()就是出现错误,string通过memcpy()拷贝后,程序就会蹦,因为mencpy()函数是浅拷贝,他只是把string实例化的这个对象的内存拷贝过去,_str浅拷贝过去,当出了这个作用域后,string调用自己的析构函数,因为一块地址被两个指针所指向,析构第二次时就会蹦。 那么解决这个问题的办法就是专门为string写一个拷贝函数,但是这样没有普遍性,写一个类专门写一个函数会很麻烦,模版的类型萃取就很好的解决了这个办法,提高了运算效率,当对象是内置类型是使用mencpy(),当对象是自定义类型时,使用自己写的函数。下面是实现模版的类型萃取的代码。

类型萃取具体实现代码

#pragma once #include<iostream> #include<string> using namespace std; // 默认是内置类型,char,int,double.... struct True_Type { bool Get_Type() { return true; } }; //不是内置类型,比如自己定义的类,在项目中具体用到类型时,可以再自己定义 struct False_Type { bool Get_Type() { return false; } }; template <class T> struct Type_Extraction { typedef False_Type Is_Pod_Type; //Is_Pod_Type意思是平凡类型, }; //这里默认 Is_Pod_Type 就是 False_Type,因为在下面的偏特化中会 // typedef True_Type Is_Pod_Type.就会改变 Is_Pod_Type template<> struct Type_Extraction<int> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<char> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<double > { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<float> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<long long> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<bool> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<unsigned char> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<short> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<unsigned short> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<unsigned int> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<long> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<unsigned long> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<unsigned long long> { typedef True_Type Is_Pod_Type; }; template<> struct Type_Extraction<long double> { typedef True_Type Is_Pod_Type; }; template <class T> struct Type_Extraction<T*> { typedef True_Type Is_Pod_Type; }; template <class T> struct Type_Extraction<const T*> { typedef True_Type Is_Pod_Type; }; //上面都是内置类型,因为原来默认 Is_Pod_Type 是False_Type , //所以上面的模版偏特化都把 Is_Pod_Type 重命名为 True_Tpye // //使用参数(类型)推导到相应的函数模版 // //内置类型,使用memcpy并不会导致错误。 template <class T> void Copy( T* dst, T* src,size_t size,True_Type)//这里的size是数据个数 { cout << "True_Type" << endl; memcpy(dst, src, sizeof(T)*size);//memcpy 参数的size 是字节数 } //特殊类型,比如string,new时需要调用自己的构造函数时,需要自己实现拷贝,不能使用memcpy,会导致错误。 //第一种方法,根据参数类型自己选择,因为参数有False_Type,编译器会自己挑选最匹配的 template <class T> void Copy( T* dst, T* src, size_t size, False_Type) { cout << "False_Type" << endl; for (int i = 0; i < (int)size; i++) { dst[i] = src[i]; } } //第二种,根据萃取判断类型中的 Get_Type()函数的返回值判断是否是平凡类型(Is_Pod_Type) template <class T> void Copy( T* dst, T*src, size_t size) { if (Type_Extraction<T>::Is_Pod_Type().Get_Type())//如果 Is_Pod_Type 是True_Type ,Get_Type()返回值就是true. { memcpy(dst, src, sizeof(T)*size);//memcpy 参数的size 是字节数 } else { for (int i = 0; i < (int)size; i++) { dst[i] = src[i]; } } } #include<iostream> #include<string> #include"test.h" using namespace std; int main() { string s1[10] = { "ad", "adad", "adadad" }; string s2[10] = { "adadasd", "adaadadd", "adadaadadd" }; Copy(s1, s2, 5, Type_Extraction<string>::Is_Pod_Type()); cout << s1[1] << endl; int a[10] = { 1, 2, 4, 5, 6, 7, 8 }; int b[10] = { 9, 8, 8, 7, 6, 5, }; Copy(a, b, 5); cout << a[0] << endl; return 0; }
转载请注明原文地址: https://www.6miu.com/read-40097.html

最新回复(0)