C++类型萃取
功能
类型萃取,可以在模板中萃取到变量类型,对不同变量进行不同处理,可以提升程序效率.
也就是我根据你传递过来的类型,我再决定调用那种方法
在STL中用到的比较多,用于判断一个变量是否为POD类型.
简述来说可以用来判断出某个变量是内置类型还是自定义类型.
应用场景
比如我们实现顺序表,在对顺序表进行扩容时,就靠重新开辟内存、拷贝对象.
拷贝对象时,就有两种情况:一种是类型,比如int char…;还有一种是自定义类型,Data类、String类.
对于内置类型,我们可以通过memset
,来进行赋值.(扩展,浅拷贝相关的类也可以通过memset
赋值)
而对于自定义类型,大多数深拷贝的对象来说,我们必须通过调用赋值语句来赋值.
因此,我们通常在拷贝对象时,为了不出现错误,都用赋值语句来赋值.
而我们如果有一种方法/机制可以判断POD类型或者非POD类型.
对于POD类型用memset
函数,对于非POD用赋值,这样就能提高程序的效率
实现
从顺序表SeqList这里入手:
注意这个顺序表是我们自己写的一个模板类,他现在有一个问题我们需要的是一个动态存储的顺序表,所以
这里会有一个扩容的情况,但是因为模板里面你接收到的类型千奇百怪,所以不可能你只有一种扩容方法,一
个是效率低,其次有的类型你用这种方法又不行,这时候就是类型萃取大展身手的时候了。在顺序表中,当你
使用内置类型时使用realloc
扩容空间能好点,当你是自定义类型时你就得老老实实的使用别的方法了。
我先把扩容的那个函数拿出来:
void _CheckCapacity(){
if (_size >= _capacity){
if (TypeTraits <T>::__IsPODType().Get()){
cout << "这里是内置类型扩容的情况" << endl;
_a = (T*)realloc(_a, (_capacity * 2 + 3)*sizeof(T));
_capacity = _capacity * 2 + 3;
}
else{
if (_a == NULL){
_a = new T[3];
}
cout << "这里是非内置类型扩容的情况" << endl;
_capacity = _capacity * 2 + 3;
T* tmp = new T[_capacity];
if (_a){
for (size_t i = 0; i < _size; ++i){
tmp[i] = _a[i];
}
delete[] _a;
_a = tmp;
}
}
}
}
看到这里大家可能都会发现这里 if (TypeTraits <T>::__IsPODType().Get())
这句其实是最关键的,用这句来区别调用
的是哪个方法。 但是这句里面的__IsPODType()
和Get()
是哪里来的呢?
struct __TrueType{
bool Get(){
return true;
}
};
struct __FalseType{
bool Get(){
return false;
}
};
这个是TypeTraits
的模板本体,默认__IsPODType
为_FalseType
.当它为内置类型的特化时 __IsPODType
为_TureType
template <class _Tp>
struct TypeTraits{
typedef __FalseType __IsPODType;
};
//从这开始都是特化版本(类型萃取的开始)
template <>
struct TypeTraits< char>{
typedef __TrueType __IsPODType;
};
template <>
struct TypeTraits< unsigned char >{
typedef __TrueType __IsPODType;
};
为了类型萃取,我们把所有的内置类型进行特化,当然这里我只是把内置类型特化的前两个拿了出来,当T
为内置
类型时让_IsPODType
为_TureType
,所以if (TypeTraits <T>::__IsPODType().Get())
表达为真,走的是realloc
的方
法。下面看看这些代码的调用理解图:
默认的_TureType
为 _FalseType
,所以当T
为非内置类型时就走的是另外的方法,这就是类型萃取思想。
上一篇: obs-studio模块简介与源码编译
下一篇: 网站为什么被降权?网站降权原因分析