欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++类型萃取

程序员文章站 2022-06-10 13:41:45
...

C++类型萃取

功能

  类型萃取,可以在模板中萃取到变量类型,对不同变量进行不同处理,可以提升程序效率.
  也就是我根据你传递过来的类型,我再决定调用那种方法
  在STL中用到的比较多,用于判断一个变量是否为POD类型.
  简述来说可以用来判断出某个变量是内置类型还是自定义类型.
C++类型萃取

应用场景

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

拷贝对象时,就有两种情况:一种是类型,比如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的方

法。下面看看这些代码的调用理解图:
C++类型萃取
默认的_TureType_FalseType,所以当T为非内置类型时就走的是另外的方法,这就是类型萃取思想。